more models on a mvc3 page - asp.net-mvc-3

Could I have more models on a razor page?
for example when I have more grid controls each with an area(a template) for editing the data,and after that i want to save the data and see it in the grid.

You can do something like the example below (this is a very over simplified example):
public class AnimalDataViewModel
{
public List<Dog> DogData { get; set; }
public List<Cat> CatData { get; set; }
public List<Mouse> MouseData { get; set; }
public AnimalDataViewModel()
{
this.DogData = new List<Dog>();
this.CatData = new List<Cat>();
this.MouseData = new List<Mouse>();
}
}
Then in your action method:
public ActionResult DisplayAnimalDataGrids()
{
AnimalDataViewModel model = new AnimalDataViewModel();
model.DogData = this.myDataService.GetDogData();
model.CatData = this.myDataService.GetCatData();
model.MouseData = this.myDataService.GetMouseData();
return View(model);
}
Then in your view:
#model AnimalDataViewModel
#Html.Grid(Model.DogData)
#Html.Grid(Model.CatData)
#Html.Grid(Model.MouseData)

Related

how to bind a dropdownlist to model properly to be able to pass values back from view to controller

I am trying to update a compound page model which as one of its properties has a list of objects.
My Model looks like this:
public class PageViewModel
{
public ProgramListVM ProgramsDDL { get; set; }
public PageViewModel()
{
this.ProgramsDDL = new ProgramListVM();
}
}
The ProgramListVM class is:
public class ProgramListVM
{
public List<ProgramVM> Program_List { get; set; }
public int SelectedValue { get; set; }
public ProgramListVM()
{
this.Program_List = new List<ProgramVM>();
this.SelectedValue = 0;
}
}
and ProgramVM is:
public class ProgramVM
{
public int ProgramID { get; set; }
public string ProgramDesc { get; set; }
public ProgramVM(int id, string code)
{
this.ProgramID = id;
this.ProgramDesc = code;
}
}
I try to render this dropdownlist by the following two:
1-
<%: Html.DropDownList("ProgramsDDL", new SelectList(Model.Page6VM.ProgramsDDL.Program_List, "ProgramID", "ProgramDesc", Model.Page6VM.ProgramsDDL.SelectedValue))%>
2-
<%: Html.DropDownListFor(m => m.Page6VM.ProgramsDDL.Program_List, new SelectList(Model.Page6VM.ProgramsDDL.Program_List, "ProgramID", "ProgramDesc"), Model.Page6VM.ProgramsDDL.SelectedValue)%>
But when I try to update my model through a controller action
[HttpPost]
public ActionResult UpdateUser(PageViewModel model)
{
}
model.ProgramsDDL.count is zero.
What is the best way to render this dropdownlist and be able to set the selected index, and also be able to send the selected index back to the controller?
You mixed up the parameters for Html.DropDownListFor(). Code sample below should work.
<%: Html.DropDownListFor(m => m.SelectedValue,
new SelectList(Model.Page6VM.ProgramsDDL.Program_List, "ProgramID", "ProgramDesc"),
null) %>
You also should have a SelectedValue in your model that's posted back.
public class PageViewModel
{
public ProgramListVM ProgramsDDL { get; set; }
public int SelectedValue { get; set; }
public PageViewModel()
{
this.ProgramsDDL = new ProgramListVM();
}
}
Also default model binder can't map complex collections to your model. You probably don't need them in your post action anyway.

Binding ListBox with a model in MVC3

My model is
public class SiteConfig
{
public SiteConfig()
{
}
public int IdSiteConfig { get; set; }
public string Name { get; set; }
public byte[] SiteLogo { get; set; }
public string Brands { get; set; }
public string LinkColour { get; set; }
public IEnumerable<SiteBrand> SiteBrands { get; set; }
}
and
public class SiteBrand
{
public int Id { get; set; }
public int SiteId { get; set; }
public int BrandId { get; set; }
public Brand Brand { get; set; }
public SiteConfig SiteConfig { get; set; }
}
public class Brand
{
public int BrandId { get; set; }
public string Name { get; set; }
public IEnumerable<SiteBrand> SiteBrands { get; set; }
}
I am following Data Base first approach. Each SiteConfig record can contain one or more Brand. So Brand is saving to another table called SiteBrand.
SiteBrand contains the forign key reference to both SiteConfig(on IdSiteConfig) and Brand(BrandId).
When I am creating a SiteConfig I want to display all the available Brand as list box where user can select one or many record(may not select any brand).
But when I bind my view with the model how can I bind my list box to the list of brands and when view is posted how can I get the selected brands.
And I have to save the SiteConfig object to database with the selected Items. And this is my DB diagram.
This is my DAL which saves to db.
public SiteConfig Add(SiteConfig item)
{
var siteConfig = new Entities.SiteConfig
{
Name = item.Name,
LinkColour = item.LinkColour,
SiteBrands = (from config in item.SiteBrands
select new SiteBrand {BrandId = config.BrandId, SiteId = config.SiteId}).
ToList()
};
_dbContext.SiteConfigs.Add(siteConfig);
_dbContext.SaveChanges();
return item;
}
Can somebody advide how to bind the list box and get the selected items.
Thanks.
Add a new Property to your SiteConfig ViewModel of type string array. We will use this to get the Selected item from the Listbox when user posts this form.
public class SiteConfig
{
//Other properties here
public string[] SelectedBrands { get; set; } // new proeprty
public IEnumerable<SiteBrand> SiteBrands { get; set; }
}
In your GET action method, Get a list of SiteBrands and assign to the SiteBrands property of the SiteConfig ViewModel object
public ActionResult CreateSiteConfig()
{
var vm = new SiteConfig();
vm.SiteBrands = GetSiteBrands();
return View(vm);
}
For demo purposes, I just hard coded the method. When you implement this, you may get the Data From your Data Access layer.
public IList<SiteBrand> GetSiteBrands()
{
List<SiteBrand> brands = new List<SiteBrand>();
brands.Add(new SiteBrand { Brand = new Brand { BrandId = 3, Name = "Nike" } });
brands.Add(new SiteBrand { Brand = new Brand { BrandId = 4, Name = "Reebok" } });
brands.Add(new SiteBrand { Brand = new Brand { BrandId = 5, Name = "Addidas" } });
brands.Add(new SiteBrand { Brand = new Brand { BrandId = 6, Name = "LG" } });
return brands;
}
Now in your View, which is strongly typed to SiteConfig ViewModel,
#model SiteConfig
<h2>Create Site Config</h2>
#using (Html.BeginForm())
{
#Html.ListBoxFor(s => s.SelectedBrands,
new SelectList(Model.SiteBrands, "Brand.BrandId", "Brand.Name"))
<input type="submit" value="Create" />
}
Now when user posts this form, you will get the Selected Items value in the SelectedBrands property of the ViewModel
[HttpPost]
public ActionResult CreateSiteConfig(SiteConfig model)
{
if (ModelState.IsValid)
{
string[] items = model.SelectedBrands;
//check items now
//do your further things and follow PRG pattern as needed
}
model.SiteBrands = GetBrands();
return View(model);
}
You can have a "ViewModel" that has both the site and brand model in it. Then you can bind your view to that model. This would allow you to bind any part of the view to any part of any of the underlying models.
public class siteViewModel{
public SiteConfig x;
public Brand b; //Fill this with all the available brands
}
Of course you can include any other information your view might need (reduces the need of ViewBag as well).

RequiredIf validation in asp.net mvc3

I had a view model in that viewmodel i created two different instances using same model like this:
public ClaimViewModel()
{
engineClaim = new ClaimModel();
boatClaim = new ClaimModel();
}
public ClaimModel engineClaim { get; set; }
public ClaimModel boatClaim { get; set; }
I had properties in ClaimModel like this:
[Required]
public string Complaint { get; set; }
[RequiredIf("isEngineClaim", true , ErrorMessage = "Required")]
public string Cause { get; set; }
[Required]
public string Correction { get; set; }
public bool isEngineClaim { get; set; }
And in controller i am loading the index page like this
public ActionResult Index()
{
ViewBag.Message = "Welcome to ASP.NET MVC!";
ClaimViewModel claim = new ClaimViewModel();
claim.engineClaim = new Models.ClaimModel();
claim.engineClaim.isEngineClaim = true;
claim.boatClaim = new Models.ClaimModel();
claim.boatClaim.isEngineClaim = false;
return View("Index", claim);
}
Now my problem is the requiredif validation is not working though the 'isEngineClaim' property is different for two instances. I am following this link
And moreover i had placed the hidden field of 'isEngineClaim' in my view also. But the requiredifvalidation is not working can anyone suggest me the solution.

Populating Dropdowns in ASP.NET MVC 3

I need to populate a dropdown in ASP.NET MVC 3. I was hoping to get the answers to the following questions:
What options do I have. I mean what's the difference between #Html.DropDownList and #Html.DropDownListFor. Also are there any other options?
I have the following classes/code. What would be the razor code/HTML syntax I need (I have included what I was trying) in my .cshtml assuming I need to only show this dropdown using the classes below.
public class SearchCriterion
{
public int Id { get; set; }
public string Text { get; set; }
public string Value { get; set; }
}
public class SearchCriteriaViewModel
{
public IEnumerable<SelectListItem> SearchCriteria { get; set; }
}
public class HomeController : Controller
{
public ActionResult Index()
{
IList<System.Web.WebPages.Html.SelectListItem> searchCriteriaSelectList =
new List<System.Web.WebPages.Html.SelectListItem>();
SearchCriteriaViewModel model = new SearchCriteriaViewModel();
//Some code to populate searchCriteriaSelectList goes here....
model.SearchCriteria = searchCriteriaSelectList;
return View(model);
}
}
//Code for Index.cshtml
#model SearchCriteriaViewModel
#{
ViewBag.Title = "Index";
}
<p>
#Html.DropDownListFor(model => model.SearchCriteria,
new SelectList(SearchCriteria, "Value", "Text"))
</p>
the right side of the lambda => has to be a simple type not the complex type modify your code like
public class SearchCriteriaViewModel
{
public int Id { get; set; }
public IEnumerable<SearchCriterion> SearchCriteria { get; set; }
}
public class SearchCriterion
{
public string Text { get; set; }
public string Value { get; set; }
}
the controller will look like
public ActionResult Index()
{
//fill the select list
IEnumerable<SearchCriteria> searchCriteriaSelectList =
Enumerable.Range(1,5).Select(x=>new SearchCriteria{
Text= x.ToString(),
Value=ToString(),
});
SearchCriteriaViewModel model = new SearchCriteriaViewModel();
//Some code to populate searchCriteriaSelectList goes here....
model.SearchCriteria = searchCriteriaSelectList;
return View(model);
}
in the view
#model SearchCriteriaViewModel
#{
ViewBag.Title = "Index";
}
<p>
#Html.DropDownListFor(model => model.Id,
new SelectList(model.SearchCriteria , "Value", "Text"))
</p>
After extensively using ASP.NET MVC for the past 3 years, I prefer using additionalViewData from the Html.EditorFor() method more.
Pass in your [List Items] as an anonymous object with the same property name as the Model's property into the Html.EditorFor() method.
The benefit is that Html.EditorFor() method automatically uses your Editor Templates.
So you don't need to provide CSS class names for your Drop Down Lists.
See comparison below.
//------------------------------
// additionalViewData <=== RECOMMENDED APPROACH
//------------------------------
#Html.EditorFor(
m => m.MyPropertyName,
new { MyPropertyName = Model.ListItemsForMyPropertyName }
)
//------------------------------
// traditional approach requires to pass your own HTML attributes
//------------------------------
#Html.DropDown(
"MyPropertyName",
Model.ListItemsForMyPropertyName,
new Dictionary<string, object> {
{ "class", "myDropDownCssClass" }
}
);
//------------------------------
// DropDownListFor still requires you to pass in your own HTML attributes
//------------------------------
#Html.DropDownListFor(
m => m.MyPropertyName,
Model.ListItemsForMyPropertyName,
new Dictionary<string, object> {
{ "class", "myDropDownCssClass" }
}
);
If you want more details, please refer to my answer in another thread here.

How can I get the values from a ListBox in my ASP.NET MVC 3 controller?

Here is my Item class:
public class Item
{
public int ItemId { get; set; }
public string Name { get; set; }
public virtual List<Tag> Tags { get; set; }
}
Here's my GET action:
//
// GET: /Home/AddItem/
public ActionResult AddItem()
{
List<Tag> Tags = Db.Tags.ToList();
ViewBag.Tags = new SelectList(Tags, "TagId", "Name");
return View();
}
Here's my view:
#model MySite.Models.Item
#using (Html.BeginForm()) {
//...
#Html.ListBox("Tags")
//...
}
Finally, here's my POST action:
//
// POST: /Home/AddItem/
[HttpPost]
public ActionResult AddItem(Item Item)
{
//...
List<Tag> NewItemTags = Item.Tags.ToList();
//...
}
The problem is that Item.Tags.ToList() is always empty in the POST action... like the selected values of the ListBox aren't being sent at all.
Stuck here. Please help.
I am assuming that TagId is integer.
public class Item
{
public int ItemId { get; set; }
public string Name { get; set; }
public virtual List<int> Tags { get; set; }
}
[HttpPost]
public ActionResult AddItem(Item Item)
{
List<int> NewItemTags = Item.Tags.ToList();
}
Also in View your ListBox should have Name = "Tags". If you are using ListBoxFor then no need to worry.
If still issue provide further information related to view.

Resources