Use variable from controller in view ASP.NET MVC4 - asp.net

There is a model in my project
using System;
namespace Argussite.SupplierServices.ViewModels
{
public class UsersPage
{
public Guid SupplierId { get; set; }
public string SupplierFullName { get; set; }
public bool ActionsAllowed { get; set; }
}
}
I use my model in controller and set properties
public ActionResult Index(Guid id)
{
var supplierOfUser = Context.Suppliers.AsNoTracking()
//.Include(e => e.Supplier)
.FirstOrDefault(e => e.Id == id);
string SupplierId = id.ToString();
string SupplierFullName = supplierOfUser.FullName.ToString();
bool ActionsAllowed = supplierOfUser.Active;
return View();
}
and then I need to use that in view, but I don't know how to get my properties in the view?

Firstly your controller action needs to send that model instance to the view like this:
return View(supplierOfUser);
You need this at the top of your view:
#model Argussite.SupplierServices.ViewModels.UsersPage
Then all you need to do is whereever you want to use your model in the view do:
#Model.SupplierFullName
If you want to use other properties in the view that you can place them into a dynamic ViewBag variable like this:
ViewBag.supplierOfUser = supplierOfUser.FullName.ToString();
and then on your view you can use this value like this:
#ViewBag.supplierOfUser

Create a new UsersPage and assign the properties you already have to its properties, then pass the newly created UsersPage to the view:
public ActionResult Index(Guid id)
{
var supplierOfUser = Context.Suppliers.AsNoTracking()
//.Include(e => e.Supplier)
.FirstOrDefault(e => e.Id == id);
var usersPage = new UsersPage();
usersPage.SupplierId = id.ToString();
usersPage.SupplierFullName = supplierOfUser.FullName.ToString();
usersPage.ActionsAllowed = supplierOfUser.Active;
return View(usersPage);
}

In order to use your data from the controller to the view, you need to return the view with your model in parameter:
return View(supplierOfUser);
In your view, you'd also need to define the model:
#model YourModel
Note that you don't need to set your supplier info into other variables (only supplierOfUser is required).

Best way is to establish a strongly typed model in the view:
#model Argussite.SupplierServices.ViewModels.UsersPage
Then, just reference the properties on the model, e.g.
#Html.EditorFor(model => model.SupplierFullName)

It's hard to help you with exact code as I don't know what you want to do on your view, this is a general idea of how you're supposed to pass and use your model in your view
Controller
public ActionResult Index(Guid id)
{
var supplierOfUser = Context.Suppliers.AsNoTracking()
.FirstOrDefault(e => e.Id == id);
var usersPage = new UsersPage
{
SupplierId = supplierOfUser.Id,
SupplierFullName = supplierOfUser.FullName,
ActionsAllowed = supplierOfUser.Active
}
return View(usersPage ); // <-- Send viewmodel to view
}
VIEW
// Declare model
#model Argussite.SupplierServices.ViewModels.UsersPage
...
//Use your model here at will
#Html.DisplayFor(modelItem => item.FullName)
...
#Html.EditorFor(model => model.FullName)
#Html.ValidationMessageFor(model => model.FullName)

Related

How do I create an empty model to pass to an insert-update view when there are more than on model in the dbcontext?

I need to create an empty form for database update. In the controller this is called: public ViewResult Create() => View("Edit", new List());
<TargetFramework>netcoreapp2.2</TargetFramework>
I have a class MeetingListContext : DbContext that has 3 models:
1. DbSet List
2. DbSet ATime (Look up table to show time name instead of time id)
3. DbSet DOW (Look up table to show day name instead of day id)
Model
namespace DEIGList.Models
{
public partial class MeetingListContext : DbContext
{
public MeetingListContext()
{
}
public MeetingListContext(DbContextOptions<MeetingListContext> options)
: base(options)
{
}
public virtual DbSet<ATime> ATime { get; set; }
public virtual DbSet<Dow> Dow { get; set; }
public virtual DbSet<List> List { get; set; }
The View:
#model DEIGList.Models.MeetingListContext
In the controller:
public ViewResult Create() => View("Edit", new List());
The expected result will be a form with empty data fields for fill in data.
I would like to be able to use drop downs (lookups) for the day and time.
But when I use #model DEIGList.Models.MeetingListContext I get:
InvalidOperationException: The model item passed into the ViewDataDictionary is of type 'DEIGList.Models.List', but this ViewDataDictionary instance requires a model item of type 'DEIGList.Models.MeetingListContext'.
Suggestion?
You need change from #model DEIGList.Models.MeetingListContext
to #model DEIGList.Models.List
The type of #model must same type with type of model in View("Edit", new List())
Update:
If you want to have drop down for Day and Time, you need update Controller:
public ViewResult Create() {
MeetingListContext ctx = new MeetingListContext();
ViewBag.ATime = ctx.ATime.ToList();
ViewBag.Dow = ctx.Dow.ToList();
return View("Edit", new List());
}
Add dropdown helper in View:
#Html.DropDownList("ATime", new SelectList(ViewBag.ATime, "ATimeID", "ATimeName"))
#Html.DropDownList("Dow", new SelectList(ViewBag.Dow, "DowID", "DowName"))
Your post pointed me towards a solution. The solution was to do a select with an id == 0.
var list = _context.List
.Where(l => l.ListId == 0)
.Include(t => t.ATime)
.Include(d => d.Dow)
.ToList();
ViewBag.thelist = list;
return View("Edit", new List());

Html.DropDownListFor set selected value

I create a #Html.DropDownListFor and populate it from the database. How can I set a selected value to the drop down?
My View:
#Html.DropDownListFor(m => m.Forms, new SelectList(Model.Forms, "FormsCreatorID", "FormName"),
"Select a Form", new { #class = "form-control" })
My Controller:
var forms = db.formscreators.Where(fp => fp.PropertyID == id || fp.PropertyID == 0)
.OrderByDescending(x => x.PropertyID).GroupBy(x => x.FormName).Select(x => x.FirstOrDefault()).ToList();
var viewModel = new ListFormsCreator { Forms = forms };
My ViewModel:
public class ListFormsCreator
{
public List<formscreator> Forms { get; set; }
}
My Database Model:
public partial class formscreator
{
public int FormsCreatorID { get; set; }
public string FormName { get; set; }
public int PropertyID { get; set; }
}
Thanks
You should add another property to your view model for the store/pass the selected option.
public class ListFormsCreator
{
public int SelectedFormId { set;get;}
public List<formscreator> Forms { get; set; }
}
Now in your GET action, you can set that value
var viewModel = new ListFormsCreator() { Forms = forms };
viewModel.SelectedFormId = 2 ; // This will select the option with 2 as FormsCreatorID
return View(viewModel);
And in the view use the lambda expression with that property as the first parameter of the DropDownListFor helper method.
#model ListFormsCreator
#Html.DropDownListFor(m => m.SelectedFormId ,
new SelectList(Model.Forms, "FormsCreatorID", "FormName"),
"Select a Form", new { #class = "form-control" })
The DropDownListFor helper method will use the value of SelectedFormId property and select the option which has the same value attribute value from the list of options of that SELECT element.
You can also remove the dependency on formscreator class from the view model, by replacing it with a list of SelectListItem
public class ListFormsCreator
{
public int SelectedFormId { set;get;}
public List<SelectListItem> Forms { get; set; }
}
Now in your GET action, you can use the Select method to generate the lsit of SelectListItem from your other collection.
var viewModel = new ListFormsCreator();
viewModel.Forms = someCollection.Select(a=>new SelectListItem {
Value=a.FormsCreatorId.ToString(),
Text=a.FormName})
.ToList();
viewModel.SelectedFormId = 2 ; // This will select the option with 2 as FormsCreatorID
return View(viewModel);
Assuming someCollection is a collection of formscreator objects
Now in the view code is much simpler
#Html.DropDownListFor(m => m.SelectedFormId, Model.Forms ,"Select a Form")
Conform with C#/.NET naming conventions:
Rename formscreator to FormsCreator
Replace ID with Id (as it's an abbreviation, not an initialism)
Rename ListFormsCreator to something like ListFormsCreatorViewModel so it's obvious it's a ViewModel type and not a Model/Entity type.
Modify your ViewModel to add a property to store the selected FormsCreatorId value:
public class ListFormsCreatorViewModel
{
[Required] // add or remove the 'Required' attribute as necessary
public int? SelectedFormsCreatorId { get; set; }
...
}
Set the SelectedFormsCreatorId property value in your controller action if necessary if you know what the value should be.
In your POST handler, ensure the SelectedFormsCreatorId value is maintained, either by directly passing-through the model action parameter back through the View(Object viewModel) method or manually repopulating it.
The view-model property in DropDownListFor should be the SelectedFormsCreatorId property. You do not need new SelectList(...)
#Html.DropDownListFor( m => m.SelectedFormsCreatorId, this.Model.Forms );
Update your viewModel and add an Int SelectId for the dropdown selected value.
In your controller:
var viewModel = new ListFormsCreator { SelectId = PropertyId, Forms = FormSelectList(forms, PropertyId.ToString()) };
I would create a function passing in a list:
public static SelectList FormSelectList(IEnumerable<formscreators> types, string selected = null)
{
return new SelectList(from f in forms
select new SelectListItem
{
Text = f.FormName,
Value = f.FormsCreatorID.ToString()
}, "Value", "Text", selected);
}
And in your .cshtml
#Html.DropDownListFor(m => m.PropertyId, Model.forms, "Select a Form", new { #class = "form-control", required = "required" })
You should generate a 'SelectListItem' list on the controller with setting 'Selected' value and pass it via ViewBag or ViewModel. In my sample, for simplicity, I used ViewBag.
Here is the shortened Controller:
public ActionResult Edit(int? id)
{
if (id == null)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
Album album = context.Albums.Find(id);
if (album == null)
{
return HttpNotFound();
}
ViewBag.GenreId = context.Genres.Select(
g => new SelectListItem()
{
Value = g.GenreId.ToString(),
Text = g.Name,
Selected = g.GenreId == album.GenreId ? true : false
}).ToList();
return View(album);
}
Here is the shortened View Code
#using MvcMusicStore2017.Models;
#model Album
#Html.DropDownList("GenreId", null, new { #class = "form-control" })

Send Anonymous Type (List) to View in ASP.NET Core

I'm trying to send an anonymous type to my view.
The anonymous type is constructed in the following way:
public async Task<IActionResult> Historial()
{
return View(await _context.HechosLiquidador
.Select(c => new { Store = c.StoreID, LiqDate = c.FechaLFinLiq}).Distinct()
.AsNoTracking().OrderBy(s => s.LiqDate).ToListAsync());
}
The particularity of this case is that the result of the query is a list of items. How can I pass this to the view?
Should I construct a ViewModel? If that is the case, how can I populate that view model with the result of this query?
I have used a ViewModel as a solution to my problem.
ViewModel:
public class HistorialIndexData
{
public string StoreName { get; set; }
[DisplayFormat(DataFormatString = "{0:dd/MM/yyyy}", ApplyFormatInEditMode = true)]
public DateTime FechaLFinLiq { get; set; }
}
In the controller we will, at first, get the items that we want to list. Next we iterate through the object that contains those items and then store them on the ViewModel to finally be used to create a new list.
public async Task<IActionResult> Historial()
{
List<HistorialIndexData> newHistorial = new List<HistorialIndexData>();
var items = await _context.HechosLiquidador.Include(s => s.Stores)
.Select(c => new { Store = c.Stores.StoreName, LiqDate = c.FechaLFinLiq })
.Distinct()
.AsNoTracking().OrderBy(s => s.LiqDate)
.ToListAsync();
foreach(var itemtolist in items)
{
HistorialIndexData info = new HistorialIndexData
{
StoreName = itemtolist.Store,
FechaLFinLiq = itemtolist.LiqDate
};
newHistorial.Add(info);
}
return View(newHistorial);
}
Update the view to work with the ViewModel.
#model List<Application.Models.ApplicationviewModels.HistorialIndexData>

ASP.NET MVC ListBox does not show the selected list items

I am in a big trouble. I read 4 stackoverflow question and one blogpost. I have tried 5 different approach to view the selected items in a multiple selectlist.
I have no success.
The multiple selectlist is generated, but it does not select the items. I have no more idea.
Model:
public class EditableModel
{
public IList<Company> SelectedCompanies { get; set; }
public IList<SelectListItem> SelectListCompanies { get; set; }
}
Controller:
public ActionResult Edit(int id)
{
var service = _serviceDAL.GetEditableModel(id);
if (service!= null)
{
service.SelectListCompanies = GetSelectListCompanies(service.SelectedCompanies);
return View(service);
}
}
private IList<SelectListItem> GetSelectListCompanies(IList<Company> selectedCompanies)
{
List<SelectListItem> items = new List<SelectListItem>();
foreach (Companycompany in _companyService.GetCompanies())
{
items.Add(new SelectListItem
{
Value = company.CompanyId.ToString(),
Text = company.Name,
Selected = selectedCompanies.Any(x => x.CompanyId == company.CompanyId)
});
}
return items;
}
View
#Html.ListBox("SelectedCompanies", Model.SelectListCompanies, Model.SelectedCompanies.Select(x => x.CompanyId.ToString()) )
And nothing. The items in the select list is not selected...
I have tried this Multiselect, the same result, or this one as the current solution.
You cannot bind a <select multiple> to a collection of complex objects. It binds to, and posts back an array of simple values (the values of the selected options).
Your SelectedCompanies property needs to be IEnumerable<int> (assuming the CompanyId of Company is also int). Note also the Selected property of SelectListItem is ignored when binding to a property.
Your also using the same collection for the selected Companies and the list of all Companies which makes no sense. Your SelectListCompanies should be generated from your table of Company.
Model
public class MyViewModel
{
public IEnumerable<int> SelectedCompanies { get; set; }
public IEnumerable<SelectListItem> SelectListCompanies { get; set; }
}
Base on your current code for EditableModel, your code should be
public ActionResult Edit(int id)
{
var service = _serviceDAL.GetEditableModel(id);
....
MyViewModel model = new MyViewModel
{
SelectedCompanies = service.SelectedCompanies.Select(x => x.CompanyId),
SelectListCompanies = GetSelectListCompanies()
};
return View(model);
private IEnumerable<SelectListItem> GetSelectListCompanies()
{
var all companies = ... // call method to get all Companies
return companies.Select(x => new SelectListItem
{
Value = x.CompanyId.ToString(),
Text = x.Name
});
}
However, it look like you should be modifying your EditableModel and the GetEditableModel() code to return the correct data in the first place.

Multiple models in same view in asp.net mvc 4

I'm using asp.net mvc 4 & Entity Framework 6 to make a website where after user login, the table records will show & the ID of the user will show as Session. But when I run, after login, I get this error, Object reference not set to an instance of an object. I've made a custom model where two DbSet from seperate EF6 models are attached. My code is below,
Custom Model
public class MkistatVsUserLogin
{
public sample_1 sample_1 { get; set; } //Login Model
public IEnumerable<mkistat> mkistats { get; set; } //Table Model
}
Controller
[HttpPost]
public ActionResult Login(sample_1 id)
{
if (ModelState.IsValid)
{
var uservar = db.sample_1.Where(a => a.boid.Equals(id.boid)).FirstOrDefault();
if (uservar != null)
{
Session["UserBOID"] = uservar.boid.ToString();
return RedirectToAction("UserLogin");
}
}
var mkimodel = new MkistatVsUserLogin { mkistats = dsedb.mkistats.ToList() };
return View(id);
return View(mkimodel);
}
View
#model ABCoLtd.Models.MkistatVsUserLogin
#if (Session["UserBOID"] != null)
{
<li>Welcome, <b>#Session["UserBOID"].ToString()</b></li>
}
<a class="btn btn-default" href="#Url.Action("UserLogout", "Home")">Log Out</a>
#foreach (var item in Model.mkistats)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.MKISTAT_ID)
</td>
<td>
#Html.DisplayFor(modelItem => item.MKISTAT_PHONE_NO)
</td>
</tr>
}
Is there something wrong with my code? If it is then please give me a solution. All I want is to use both models at the same view where user login model will be used in Session & table model to list all the records.
Remove bellow line
return View(id);
and in your return View line also mention View or ActionMethod name
return View("ViewName",mkimodel)
In your action method, Use Session to pass ID
Session["UserID"] = id;
You can use the same in your View as :
<html>
-----Your CODE
<body>
------Your CODE
#Session["UserID"]
------Your CODE
</body>
</html>
You can create a ViewModel to handle :
namespace ABCoLtd.ViewModels
{
public class LoginVM
{
public MkistatVsUserLogin MkistatVsUserLogin {get;set;}
public int Id {get;set;}
}
}
and in action pass this way:
var mkimodel = new MkistatVsUserLogin { mkistats = dsedb.mkistats.ToList() };
LoginVM vm = new LoginVM();
vm.MkistatVsUserLogin = mkimodel ;
vm.Id = id;
return View(vm );
and in View set model to LoginVM:
#model ABCoLtd.ViewModels.LoginVM
UPDATE:
you already have a viewmodel didnt noticed that, you just need to do this:
var mkimodel = new MkistatVsUserLogin
{
mkistats = dsedb.mkistats.ToList(),
sample_1 = id
};
return View(nkimodel);
After login you are directly redirecting your user to an action and that action you have not mentioned here.And that action whose view you have shown is an strongly typed view which expects a list of MkistatVsUserLogin. But, I think you are not passing that list, so Model property of view will remain null and that will be causing an error of object reference. Please check this issue.
I got it. I just made another method in controller for viewing table with user session.
[HttpPost]
public ActionResult Login(sample_1 id)
{
if (ModelState.IsValid)
{
var uservar = db.sample_1.Where(a => a.boid.Equals(id.boid)).FirstOrDefault();
if (uservar != null)
{
Session["UserBOID"] = uservar.boid.ToString();
return RedirectToAction("UserLogin");
}
}
return View(id);
}
public ActionResult UserLogin()
{
if(Session["UserBOID"] != null)
{
var mkimodel = new MkistatVsUserLogin { mkistats = dsedb.mkistats.ToList() };
return View(mkimodel);
}
else
{
return RedirectToAction("Login");
}
}

Resources