The model item is of type CookMeIndexViewModel, but requires a model item of type IEnumerable<CookMeIndexViewModel> - asp.net

I am following along with the music store example to try learn ASP.NET MVC. I'm creating a cookbook application.
I have created my viewmodel that looks like this:
namespace CookMe_MVC.ViewModels
{
public class CookMeIndexViewModel
{
public int NumberOfReceipes { get; set; }
public List<string> ReceipeName { get; set; }
}
}
my controller looks like this
public ActionResult Index()
{
var meals= new List<string> { "Dinner 1", "Dinner 2", "3rd not sure" };
//create the view model
var viewModel = new CookMeIndexViewModel
{
NumberOfReceipes = meals.Count(),
ReceipeName = meals
};
return View(viewModel);
}
Finally my view looks like this
#model IEnumerable<CookMe_MVC.ViewModels.CookMeIndexViewModel>
#{
ViewBag.Title = "Index";
}
<h2>Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th></th>
<th>
Meals
</th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Details", "Details", new { /* id=item.PrimaryKey */ }) |
#Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })
</td>
<td>
#item.ReceipeName
</td>
</tr>
}
</table>
I get this error.
The model item passed into the dictionary is of type CookMeIndexViewModel, but this dictionary requires a model item of type IEnumerable<CookMeIndexViewModel>.
I have followed the example. I can't see what I am doing wrong. Should I be returning my viewmodel as a generic list?

In your view you are using #model IEnumerable<CookMe_MVC.ViewModels.CookMeIndexViewModel> which indicates that the model expected by the View is of type IEnumerable of CookMeIndexViewModel.
However in the controller you are passing an object of type CookMeIndexViewModel as a model return View(viewModel); hence the error.
Either change the view to have #model CookMe_MVC.ViewModels.CookMeIndexViewModel
or pass a IEnumerable of CookMeIndexViewModel as model to the view in controller as given below:
public ActionResult Index()
{
var meals= new List<string> { "Dinner 1", "Dinner 2", "3rd not sure" };
//create the view model
var viewModel = new CookMeIndexViewModel
{
NumberOfReceipes = meals.Count(),
ReceipeName = meals
};
List<CookMeIndexViewModel> viewModelList = new List<CookMeIndexViewModel>();
viewModelList.Add(viewModel);
return View(viewModelList);
}

I got this message when I had a conflict between what the #model directive in the _Layout.cshtml layout view and an "inner page" view.
The _Layout.cshtml had directive..
#model MyProject.Models.MyObject
My inner page had...
#model IEnumerable<MyProject.Models.MyObject>
I was working on some test / experiment code and hit this issue when I created new controller etc. It was only when I renamed Model Object and compiled afterwards that I found the source of the problem.
Hope this helps.
Q.

in kendo ui Grid do :
public class BookBean
{
[ScaffoldColumn(false)]
public Int32 Id { set; get; }
public String Title { set; get; }
public String Author { set; get; }
public String Publisher { set; get; }
[UIHint("Integer")]
public Int32 Price { set; get; }
[UIHint("Integer")]
public Int32 Instore { set; get; }
[UIHint("Integer")]
public Int32 GroupId { get; set; }
}
in Integer.ascx in Shared/EditorTemplate folder do :
<%# Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<int?>" %>
<%: Html.Kendo().IntegerTextBoxFor(m => m)
.HtmlAttributes(new { style = "width:100%" })
.Min(int.MinValue)
.Max(int.MaxValue)
%>

Related

Binding list of nested viewmodels on post ASP.NET MVC

I have the following viewmodel structure:
ItemViewModel containing a property Model of type BaseViewModel.
In this concrete example, Model is of type WeekManagerWorkScheduleViewModel. This viewmodel in turns consists of an IEnumerable of type ManagerWorkScheduleViewModel.
Inside the ItemView.cshtml the following is used:
<form class="form-horizontal" id="#Model.FormName" name="#Model.FormName" onsubmit="#Model.OnSubmitFunction">
<div class="form-group form-group-sm">
#Html.EditorFor(model => model.Model, Model.ItemViewName + "View")
</div>
<button class="btn pull-left" type="submit" style="margin: 2px;">
<span class="glyphicon glyphicon-save"></span>
#Model.ViewConfiguration.SaveText #Model.ItemTitle
</button>
</form>
I have omitted some details (basically a bunch of if's determining whether or not to add CRUD buttons. The Model.ItemViewName is the typename (in this case its WeekManagerWorkScheduleViewModel).
public class WeekManagerWorkScheduleViewModel : BaseViewModel
{
[HiddenInput]
public int RegionId { get; set; }
[HiddenInput]
public IEnumerable<DateTime> Dates { get; set; }
public IEnumerable<ManagerWorkScheduleViewModel> WorkSchedules { get; set; }
}
The WeekManagerWorkScheduleView.cshtml looks like this:
#using DRSTransportPortal.ViewModels
#model WeekManagerWorkScheduleViewModel
#{
ViewBag.Title = "Ugentlig arbejdsplan - ledere";
}
#Html.HiddenFor(m => m.RegionId)
<table class="table">
<thead>
<tr>
<th><b>Leder</b></th>
<th><b>Uge</b></th>
<th><b>Mandag</b></th>
<th><b>Tirsdag</b></th>
<th><b>Onsdag</b></th>
<th><b>Torsdag</b></th>
<th><b>Fredag</b></th>
<th><b>Lørdag</b></th>
<th><b>Søndag</b></th>
</tr>
<tr>
<th></th>
<th></th>
#foreach (var date in Model.Dates)
{
<th><i><small>#date.Date.ToString("dd-MM-yyyy")</small></i></th>
}
</tr>
</thead>
<tbody>
#Html.EditorFor(m => m.WorkSchedules)
</tbody>
</table>
I have a view called ManagerWorkScheduleViewModel.cshtml residing in Views/imalazysod/EditorTemplates (MVC knows this location, as I am using a custom view engine, derived from Razor):
#using DRSTransportPortal.ViewModels
#model ManagerWorkScheduleViewModel
<tr id="#Model.Id">
<td>#Html.HiddenFor(m => m.Id)</td>
<td>#Html.DisplayFor(m => m.ManagerName, new { htmlAttributes = new { #class = "form-control editoritem" } })</td>
<td>#Html.DisplayFor(m => m.DateWeekText, new { htmlAttributes = new { #class = "form-control editoritem" } })</td>
<td>#Html.EditorFor(m => m.MondayCodeChoice, new { #class = "form-control editoritem" })</td>
<td>#Html.EditorFor(m => m.TuesdayCodeChoice, new { #class = "form-control editoritem" })</td>
<td>#Html.EditorFor(m => m.WednesdayCodeChoice, new { #class = "form-control editoritem" })</td>
<td>#Html.EditorFor(m => m.ThursdayCodeChoice, new { #class = "form-control editoritem" })</td>
<td>#Html.EditorFor(m => m.FridayCodeChoice, new { #class = "form-control editoritem" })</td>
<td>#Html.EditorFor(m => m.SaturdayCodeChoice, new { #class = "form-control editoritem" })</td>
<td>#Html.EditorFor(m => m.SundayCodeChoice, new { #class = "form-control editoritem" })</td>
</tr>
The "Choice" properties are all of type ChoiceViewModel using a ChoiceViewModel.cshtml.
Now, everything renders fine:
Screenshot (names omitted). Red box indicates 1 (one) nested viewmodel
The generated HTML looks like this (only the first row and first few cells are shown here):
<tr id="134">
<td><input name="Model.WorkSchedules[0].Id" id="Model_WorkSchedules_0__Id" type="hidden" value="134" data-val-required="Feltet Id skal udfyldes." data-val="true" data-val-number="The field Id must be a number."></td>
<td>OMITTED</td>
<td>2016 - 36</td>
<td>
<select name="Model.WorkSchedules[0].MondayCodeChoice.SelectedValue" class="form-control editoritem dropdown" id="SelectChoices" onchange="">
<option value="1">06:00 - 14:00</option>
<option value="19">06:00 - 18:00</option>
<option value="31">08:00 - 16:00</option>
<option value="2">10:00 - 18:00</option>
<option value="32">10:00 - 18:00</option>
<option value="23">Bagvagt</option>
<option value="22">Ferie</option>
<option value="8">Fri</option>
<option value="3">Kontor</option>
<option value="15">Kussus</option>
<option value="16">Syg</option>
</select>
</td>
REST OF HTML IS OMMITTED (CONTINUES FOR 12 ROWS WITH 10 CELLS EACH)
</tr>
However, when I post back (using jQuery, ajax btw) this is what I get:
Controller breakpoint, after modelbinding
I have tried putting in a custom modelbinder on the BaseViewModel, and debugging that haven't seen anything that doesn't look alright. It resolves the correct types (WeekManagerWorkScheduleViewModel, etc.).
Using that, my Forms element from ControllerContext->...->Request is:
{Model.Id=141&ModelType=DRSTransportPortal.ViewModels.WeekManagerWorkScheduleViewModel%2c+DRSTransportPortal%2c+Version%3d1.0.0.0%2c+Culture%3dneutral%2c+PublicKeyToken%3dnull&Model.RegionId=1&Model.WorkSchedules%5b0%5d.Id=134&Model.WorkSchedules%5b0%5d.MondayCodeChoice.SelectedValue=22&Model.WorkSchedules%5b0%5d.TuesdayCodeChoice.SelectedValue=1&Model.WorkSchedules%5b0%5d.WednesdayCodeChoice.SelectedValue=1&Model.WorkSchedules%5b0%5d.ThursdayCodeChoice.SelectedValue=1&Model.WorkSchedules%5b0%5d.FridayCodeChoice.SelectedValue=1&Model.WorkSchedules%5b0%5d.SaturdayCodeChoice.SelectedValue=1&Model.WorkSchedules%5b0%5d.SundayCodeChoice.SelectedValue=1&..... CONTINUES FOR ALL 12 NESTED VIEWMODELS}
I have made sure the following is true:
All bindings are made to properties (default ie. {get;set;})
No viewmodels, including BaseViewModel, have constructors (ie. default constructors should be created)
All properties and classes are public
So...my question is, why is the modelbinder unable to create the viewmodels of the list? I have no problem using the template elsewhere, editing pr. person, ie. one row at a time).
Yes, I know there are MANY questions and MANY answers related to MVC modelbinding, but none seem to quite fall into this category (same goes for books). What really puzzles me, is that it is recognized that a list of 12 items is needed, but it just isn't populated.
EDIT:
public class BaseViewModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
var typeValue = bindingContext.ValueProvider.GetValue("ModelType");
var type = Type.GetType((string) typeValue.ConvertTo(typeof (string)), true);
if(!typeof(BaseViewModel).IsAssignableFrom(type))
throw new InvalidOperationException("NOT A BASEVIEWMODEL");
var model = Activator.CreateInstance(type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, type);
return model;
}
}
[ModelBinder(typeof(BaseViewModelBinder))]
public class BaseViewModel
{
[HiddenInput]
public int Id { get; set; }
[HiddenInput]
public DateTime Created { get; set; }
[HiddenInput]
public DateTime Edited { get; set; }
public virtual string SelectionName { get; set; }
}
EDIT 2:
[HttpPost]
public override async Task<JsonResult> Save(ItemViewModel item, string parentName, int? parentId)
{
if (item?.Model == null)
{
const int result = 0;
return Json(new { result });
}
var model = item.Model as WeekManagerWorkScheduleViewModel;
if (model == null)
{
const int result = 0;
return Json(new { result });
}
foreach (var inner in model.WorkSchedules)
{
}
return await base.Save(item, parentName, parentId);
}
public class ManagerWorkScheduleViewModel : BaseViewModel
{
[HiddenInput]
public int? ManagerId { get; set; }
[DisplayName("Leder")]
public string ManagerName { get; set; }
[HiddenInput]
public int? DateWeekId { get; set; }
[DisplayName("År / Uge")]
public string DateWeekText { get; set; }
[HiddenInput]
public int? MondayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Mandag")]
public ChoiceViewModel MondayCodeChoice { get; set; }
[HiddenInput]
public int? TuesdayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Tirsdag")]
public ChoiceViewModel TuesdayCodeChoice { get; set; }
[HiddenInput]
public int? WednesdayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Onsdag")]
public ChoiceViewModel WednesdayCodeChoice { get; set; }
[HiddenInput]
public int? ThursdayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Torsdag")]
public ChoiceViewModel ThursdayCodeChoice { get; set; }
[HiddenInput]
public int? FridayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Fredag")]
public ChoiceViewModel FridayCodeChoice { get; set; }
[HiddenInput]
public int? SaturdayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Lørdag")]
public ChoiceViewModel SaturdayCodeChoice { get; set; }
[HiddenInput]
public int? SundayCodeId { get; set; }
[UIHint("ChoiceViewModel")]
[DisplayName("Søndag")]
public ChoiceViewModel SundayCodeChoice { get; set; }
}
Ah, stupid me.
I forgot how I actually made this framework to begin with.
I created this mainly for CRUD operations, so I only need to define viewmodel (derived from BaseViewModel), view, repository and dto types for each business entity as well as an empty controller. Then everything else is using a standard set of controllers (three levels of derivation, depending on functionality needed) and all I need to do is create a config entry for the business entity, defining the vm, view, repo types as well as some CRUD options for buttons and labels.
All top level viewmodels and view are the same, like ItemView, ItemViewModel, ItemListView, SingleSelector, MultipleSelector etc etc.
What I had FORGOTTEN was that I limited myself to one business entity at a time, hence outputting the class (see the modelbinder), so I COULD use derived viewmodels...this works great, except obviously in this case.
What happens is, as the binding tries to populate the list, it keeps trying to populate it using the first viewmodel type (as this is the only one known after POST) and not the derived. DAMMIT! So back to the drawing table (no nesting :( )

.net MVC passing linq data from controller to view

I am trying to pass data from controller to view. I have searched the web but could not find a solution.
if I do this it works:
Controller:
var yyy = (from a in Connection.Db.Authorities select a) ;
ViewBag.data = yyy;
View:
#foreach(var item in ViewBag.data)
{
#item.Value
}
But the following code does not work:
Controller:
var yyy = (from a in Connection.Db.Authorities select new {Value = a.Value, TypeCode = a.TypeCode, Return = Calculate(a.Return)}) ;
ViewBag.data = yyy;
View:
#foreach(var item in ViewBag.data)
{
#item.Value
}
It gives "item does not contain a definition for Value" for the view file.
Any help would be great.
Thank you.
-edited: updated the second controller linq query. and corrected the first controller linq query.
It's because You already select Value and Value has no such property as Value. You should change in controller:
var yyy = (from a in Connection.Db.Authorities select a.Value); to
var yyy = (from a in Connection.Db.Authorities select a);
OR change the view to
#foreach(var item in ViewBag.data)
{
#item
}
//////////////////////////////////////////////// EDITS ////////////////////////////////////////////////
Than You should not use anonymous object. You should create ViewModelClass. For Example:
public class AuthoritiesViewModel
{
public string Value { get; set; }
public string TypeCode { get; set; }
public string Return { get; set; }
}
And change your controller:
var yyy = (from a in Connection.Db.Authorities select new AuthoritiesViewModel{ Value = a.Value, TypeCode = a.TypeCode, Return = Calculate(a.Return)});
ViewBag.data = yyy;
and in your view you will be able to use:
<table>
<tr>
<th>Value</th>
<th>TypeCode</th>
<th>Return</th>
</tr>
#foreach(AuthoritiesViewModel item in ViewBag.data)
{
<tr>
<td>#item.Value<td>
<td>#item.TypeCode<td>
<td>#item.Return<td>
</tr>
}
</table>
Also, I have a question to You. Why do You use ViewBag to pass data from controller to view? Why don't You use Model to pass these data to view according to MVC pattern?
//////////////////////////////////////////////// MORE EDITS ////////////////////////////////////////////////
To send more than one query result You can create more complex model. For example:
public class AuthoritiesViewModel
{
public string Value { get; set; }
public string TypeCode { get; set; }
public string Return { get; set; }
}
public class AnotherQueryViewModel
{
public string AnotherQueryValue { get; set; }
public string AnotherQueryTypeCode { get; set; }
public string AnotherQueryReturn { get; set; }
}
public class ModelClass
{
IEnumerable<AuthoritiesViewModel> Authorities { get; set; }
IEnumerable<AnotherQueryViewModel> AnotherQueryResults { get; set; }
}
And change the controller:
var yyy = (from a in Connection.Db.Authorities select new AuthoritiesViewModel{ Value = a.Value, TypeCode = a.TypeCode, Return = Calculate(a.Return)});
// do your another select
var zzz = (from smthing select new AnotherQueryViewModel ...)
// create model instance
ModelClass model = new ModelClass()
{
Authorities = yyy.AsEnumerable(),
AnotherQueryResults = zzz..AsEnumerable()
}
// return view with model
return View("view", model);
and in view you can use:
#model ModelClass
#*display first query result*#
<table>
<tr>
<th>Value</th>
<th>TypeCode</th>
<th>Return</th>
</tr>
#foreach(AuthoritiesViewModel item in Model.Authorities)
{
<tr>
<td>#item.Value<td>
<td>#item.TypeCode<td>
<td>#item.Return<td>
</tr>
}
</table>
#*display second query result*#
<table>
<tr>
<th>Another Query Value</th>
<th>Another Query TypeCode</th>
<th>Another Query Return</th>
</tr>
#foreach(AnotherQueryViewModel item in Model.AnotherQueryResults)
{
<tr>
<td>#item.AnotherQueryValue<td>
<td>#item.AnotherQueryTypeCode<td>
<td>#item.AnotherQueryReturn<td>
</tr>
}
</table>
use sth like this
ViewBag.qualification = new SelectList(db.Lookups.Where(x => x.lookup_type == "Qualification"), "lookup_content", "lookup_content");

asp net mvc3 post a list of objects to action

I created a page with aspnet mvc3. It show all users info as a list. I want to do something with this list. There are some checkboxes that belong to each items. When I click some checkboxes and press submit button, I want to post the whole list as a collection and save each items of this collection to database. There are several notes on internet but there is no exact solution. I have a UserDto. and want to use this to transfer users data in all sections.
Does anyone have any full solution about this or can they give any idea?
Thanks in advance.
Kerem
I added some of my codes. You can see the lead sentences what they are about.
this is my index view detail:
#model List<DomainModel.UserApprovalDto>
#{
ViewBag.Title = "Manage Users";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>
Manage Users</h2>
<div>#Html.Partial("_PartialManageUsers", (List<DomainModel.UserApprovalDto>)Model) </div>
this is my partial view detail:
#model List<DomainModel.UserApprovalDto>
#using (Html.BeginForm("ConfirmUsers", "ManageUsers", FormMethod.Post))
{
<table>
<tr>
<th>
Name
</th>
<th>
Is Reported
</th>
</tr>
#for (int i = 0; i < Model.Count(); i++)
{
<tr>
<td>
#Html.DisplayFor(modelItem => Model[i].FirstName)
</td>
<td>
#Html.CheckBox("IsReported", Model[i].IsReported.HasValue ? Model[i].IsReported.Value : false)
#*#Html.CheckBoxFor(modelItem => Model[i].IsReported.Value);*# #* #if (Model[i].IsReported != null)
{
#Html.CheckBoxFor(modelItem => Model[i].IsReported.Value);
}
else
{
#Html.CheckBoxFor(modelItem => Model[i].IsReported.Value);
}*#
</td>
<td>
</td>
</tr>
}
</table>
<div>
<input name="submitUsers" type="submit" value="Save" />
</div>
}
this is my controller submit method
[HttpPost]
public ActionResult ConfirmUsers(List<DomainModel.UserApprovalDto> collection)
{
if (ModelState.IsValid)
{
//TO-DO
}
return RedirectToAction("Index");
}
this last one is my DTO class detail:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DomainModel
{
public class UserApprovalDto
{
public long UserId { get; set; }
public Guid CarUserId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhotoPath { get; set; }
public string PhotoSmallPath { get; set; }
public string PhotoSquarePath { get; set; }
public string PhotoBigPath { get; set; }
public bool IsBlocked { get; set; }
public bool IsDeleted { get; set; }
}
}
when I submit this code my list return null collection to my controller method.
thanks for your comments.
Assuming you are creating a screen which adds/ remove users to a course. So let's create some viewmodels
public class CourseVM
{
public string Name { set;get;}
public int CourseID { set;get;}
public List<UserVM> Users { set;get;}
public CourseVM()
{
Users=new List<UserVM>();
}
}
public class UserVM
{
public string Name { set;get;}
public int UserID{ set;get;}
public bool IsSelected { set;get;}
}
Now in your GET Action, you will fill the values of the ViewModel and sent it to the view.
public ActionResult Add()
{
var vm = new CourseVM();
//The below code is hardcoded for demo. you may replace with DB data.
vm.Users.Add(new UseVM { Name = "Jon" , UserID=1});
vm.Users.Add(new UseVM { Name = "Scott", UserID=2 });
return View(vm);
}
Now Let's create an EditorTemplate. Go to Views/YourControllerName and Crete a Folder called "EditorTemplates" and Create a new View there with the same name as of the Property Name(UserVM.cshtml)
Add this code to your new editor template.
#model ChannelViewModel
<p>
<b>#Model.Name</b> :
#Html.CheckBoxFor(x => x.IsSelected) <br />
#Html.HiddenFor(x=>x.Id)
</p>
Now in your Main View, Call your Editor template using the EditorFor Html Helper method.
#model CourseVM
#using (Html.BeginForm())
{
<div>
#Html.EditorFor(m=>m.Users)
</div>
<input type="submit" value="Submit" />
}
Now when you post the form, Your Model will have the Users Collection where the Selected Checkboxes will be having a True value for the IsSelected Property.
[HttpPost]
public ActionResult Add(CourseVM model)
{
if(ModelState.IsValid)
{
//Check for model.Users collection and Each items
// IsSelected property value.
//Save and Redirect(PRG pattern)
}
return View(model);
}

Pass a model to an MVCMailer view

I have a controller, which passes a model (ovw.ToList()) to a view:
//
// GET: /Clinic/Overview/
public ActionResult Overview()
{
IEnumerable<Clinic> ovw = from c in db.Clinics
select c;
return View(ovw.ToList());
}
View:
#model IEnumerable<ttp.Models.Clinic>
#foreach (var item in Model)
{
<div>#item.ClinicName</div>
#foreach (var item2 in item.Properties)
{
<div>#item2.Address</div>
This works absolutely fine on screen.
When using MVCMailer, however , if I want to display the same layout in the email, how do I pass the ovw.ToList() to the mailer view, so that I can reference the same model in this way:
(I'm stuck on what to put in as the first line in the view):
#model IEnumerable<ttp.Models.Clinic>
#foreach (var item in Model)
Thanks for any help,
Mark
You should find your answer in the 'Pass Data to Mailer Views' part of this guide: https://github.com/smsohan/MvcMailer/wiki/MvcMailer-Step-by-Step-Guide
To pass your model along with the view to MVCMailer, you need to use ViewData:
var comment = new Comment {From = me, To = you, Message = "Great Work!"};
ViewData = new ViewDataDictionary(comment);
In my project i doing like this it's below
i am showing all my category list in my index view
in my model class
public List<CategoryDetails> CategoryData { get; set; }
and i am also create CategoryDetails class and create a property to all my field
like this
public int CatID { get; set; }
[Required(ErrorMessage = "Enter Category Name")]
public string CatName { get; set; }
public string CatImage { get; set; }
and create a function in my main model class like this
public void LoadCategory()
{
CategoryData = (from con in dbData.Categorys
select new CategoryDetails()
{
CatID = con.CatID,
CatName = con.CatName,
CatImage = con.CatImage,
}).ToList();
}
In my controller i create a action like this
create my model class object and pass my model function to action
public ActionResult Index()
{
CategoryModel categorymodel = new CategoryModel();
categorymodel.LoadCategory();
return View(categorymodel);
}
and in my view
#model PMS.Models.CategoryModel
#{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>
Index</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table>
<tr>
<th>
Category Name
</th>
<th>
</th>
</tr>
#foreach (var item in Model.CategoryData)
{
<tr>
<td>
#Html.DisplayFor(modelItem => item.CatName)
</td>
</tr>
}
</table>
i think this will help you

Binding model with child list MVC 3 razor

I have the following model :
public class ContratoDetailsViewModel
{
[StringLength(50)]
[RegularExpression("^[a-z0-9_\\+-]+(\\.[a-z0-9_\\+-]+)*#[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,4})$")]
[DisplayName("E-Mail Adm.")]
public string emailAdm { get; set; }
}
public class ContratoDetailContainerViewModel
{
public ContratoDetailsViewModel contrato { get; set; }
public IList<ContratoModels.CCasinoViewModel> ccasinos { get; set; }
}
public class CCasinoViewModel
{
public short codigo { get; set; }
public List<SelectListItem> listCasinos { get; set; }
}
the following view :
#model ContratoModels.ContratoDetailContainerViewModel
#{
...
}
#using (Html.BeginForm(new { currentaction = ViewBag.mode }))
{
...
#Html.EditorFor(m => m.contrato.emailAdm, state1)<br />
#Html.EditorFor(m => m.ccasinos,"test")
<input type="submit" value="Save" />
}
in the folder "EditorTemplates" i have a template called "test.cshtml" :
#model List<ContratoModels.CCasinoViewModel>
#for (int i = 0; i < Model.Count(); i++)
{
#Html.DropDownListFor(m => m[i].codigo,Model[i].listCasinos)
}
My Controller post action is like this :
[HttpPost]
public ActionResult Details(ContratoModels.ContratoDetailContainerViewModel model, FormCollection form)
{
var contrato = model.contrato;
var casinos = model.ccasinos;
}
Before send the view ccasinos,codigo and listCasinos are initialised
when i am in debug mode i see the value of them... the form display work like a charm.
BUT ... when i submit the form the model.ccasinos is always null !! why ?
thank you very much for your reply.
note : I use a EditorFor with the child of my main model but if there is a better solution
for display and submit with MCV 3 I am interested ...
Try replacing:
#Html.EditorFor(m => m.ccasinos, "test")
with this:
#Html.EditorFor(m => m.ccasinos)
and then rename your test.cshtml template to CCasinoViewModel.cshtml and replace its contents with this:
#model CCasinoViewModel
#Html.DropDownListFor(x => x.codigo, Model.listCasinos)
Because the editor template is now named the same way as the type of the list, ASP.NET MVC will automatically render it for each element of this list so that you don't have to write loops.
Also you can safely remove the FormCollection argument from your action. It's completely useless when you are working with view models:
[HttpPost]
public ActionResult Details(ContratoModels.ContratoDetailContainerViewModel model)
{
var contrato = model.contrato;
var casinos = model.ccasinos;
...
}

Resources