How to use two IENumerable models in one view - asp.net-mvc

I am trying to use two models in one view, but from what I understand my program just don't see any objects within models.
Here is my code.
Models:
public class Album
{
[Key]
public int ThreadId { get; set; }
public int GenreId { get; set; }
public string Title { get; set; }
public string ThreadByUser { get; set; }
public string ThreadCreationDate { get; set; }
public string ThreadContent { get; set; }
public Genre Genre { get; set; }
public List<Posts> Posty { get; set; }
}
public class Posts
{
[Key]
public int PostId { get; set; }
public int ThreadId { get; set; }
public string PostTitle { get; set; }
public string PostContent { get; set; }
public string PostDate { get; set; }
public string PosterName { get; set; }
public Album Album { get; set; }
}
public class ModelMix
{
public IEnumerable<Posts> PostsObject { get; set; }
public IEnumerable<Album> ThreadsObject { get; set; }
}
Index controller code:
public ActionResult Index(int id)
{
ViewBag.ThreadId = id;
var posts = db.Posts.Include(p => p.Album).ToList();
var albums = db.Albums.Include(a => a.Genre).ToList();
var mixmodel = new ModelMix
{
PostsObject = posts,
ThreadsObject = albums
};
return View(mixmodel);
}
View code:
#model MvcMusicStore.Models.ModelMix
<h2>Index</h2>
#Html.DisplayNameFor(model => model.PostsObject.PostContent)
And when I try to execute my program I am getting this error:
CS1061: The "
System.Collections.Generic.IEnumerable 'does not contain a definition
of" PostContent "not found method of expanding" PostContent ", which
takes a first argument of type' System.Collections.Generic.IEnumerable
"
How I can make it work as intended? There are a lot of questions like mine on the internet but I couldn't find any matching my case.

Looping over models can be a little confusing to begin with in MVC, only because the templated helpers (i.e. Html.DisplayFor and Html.EditorFor) can be provided templates which the helper will automatically invoke for every element in a collection. That means if you're new to MVC, and you don't realise a DisplayTemplate or an EditorTemplate has not been provided for the collection already, it looks as though a simple:
#Html.DisplayFor(m => m.SomePropertyThatHoldsACollection)
is all you need. So if you've seen something like that already, that might be why you made the assumption it would work. However, let's assume for a moment that a template has not been provided. You have two options.
Firstly, and most simply, would be to use foreach over the collection:
#foreach (var post in Model.PostsObject)
{
#Html.DisplayFor(m => post.PostTitle)
// display other properties
}
You could also use a for loop, but with IEnumerable<T>, there is no indexer, so this won't work:
#for (int i = 0; i < Model.PostsObject.Count(); i++)
{
// This generates a compile-time error because
// the index post[i] does not exist.
// This syntax would work for a List<T> though.
#Html.DisplayFor(m => post[i].PostTitle)
// display other properties
}
If you did want to use the for loop still, you can use it like so:
#for (int i = 0; i < Model.PostsObject.Count(); i++)
{
// This works correctly
#Html.DisplayFor(m => post.ElementAt(i).PostTitle)
// display other properties
}
So use whichever you prefer. However, at some point it would be a good idea to look into providing templates for your types. (Note: Although this article was written for MVC 2, the advice still applies.) They allow you to remove looping logic from your views, keeping them cleaner. When combined with Html.DisplayFor, or Html.EditorFor, they will also generate correct element naming for model binding (which is great). They also allow you to reuse presentation for a type.
One final comment I'd make is that the naming of your properties is a little verbose:
public class ModelMix
{
public IEnumerable<Posts> PostsObject { get; set; }
public IEnumerable<Album> ThreadsObject { get; set; }
}
We already know they're objects, so there's no need to add that on the end. This is more readable:
public class ModelMix
{
public IEnumerable<Posts> Posts { get; set; }
public IEnumerable<Album> Threads { get; set; }
}

You need to iterate them like this:
#model MvcMusicStore.Models.ModelMix
<h2>Index</h2>
#for(var i=0; i<model.PostsObject.Count(); i++)
{
#Html.DisplayNameFor(model => model.PostsObject[i].PostContent)
}
And also it's better to save IList instead of IEnumerable, as it will have Count property, instead of using Count() method

Typically you'll need to iterate through each item if you're passing in any type of IEnumerable<>. Since you built a semi-complex model, you'll want to display foreach item in each list. Here is an example based from the ASP.NET MVC tutorials that I think would help you a bit:
#model IEnumerable<ContosoUniversity.Models.Course>
#{
ViewBag.Title = "Courses";
}
<h2>Courses</h2>
<p>
#Html.ActionLink("Create New", "Create")
</p>
<table class="table">
<tr>
<th>
#Html.DisplayNameFor(model => model.CourseID)
</th>
<th>
#Html.DisplayNameFor(model => model.Title)
</th>
<th>
#Html.DisplayNameFor(model => model.Credits)
</th>
<th>
Department
</th>
<th></th>
</tr>
#foreach (var item in Model) {
<tr>
<td>
#Html.DisplayFor(modelItem => item.CourseID)
</td>
<td>
#Html.DisplayFor(modelItem => item.Title)
</td>
<td>
#Html.DisplayFor(modelItem => item.Credits)
</td>
<td>
#Html.DisplayFor(modelItem => item.Department.Name)
</td>
<td>
#Html.ActionLink("Edit", "Edit", new { id=item.CourseID }) |
#Html.ActionLink("Details", "Details", new { id=item.CourseID }) |
#Html.ActionLink("Delete", "Delete", new { id=item.CourseID })
</td>
</tr>
}
</table>
Generally most people use an ICollection for their lists, where an example might be in an object:
public virtual ICollection<Post> Posts { get; set; }
Source:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc/reading-related-data-with-the-entity-framework-in-an-asp-net-mvc-application
I would recommend starting at the beginning as it'll help you understand why you need to do this:
http://www.asp.net/mvc/tutorials/getting-started-with-ef-using-mvc

Related

Creating a matrix of checkboxes which supports post back in ASP.NET MVC

I'm trying to think of a way to manage the selection of a matrix of values via view models in MVC 5.
I have a list of companies and a list of roles. The roles are the same for each company. What I want is to output a matrix of companies/roles with a checkbox for each combination. This allows the user to select which role the person will have for each company.
I can render the output with nested foreach loops but I can't help but think there's a better way to achieve this with MVC and Editor Templates.
Below is a crude example of the layout. So every company is output as a column and every role is output as a row. A checkbox for each company is then output into every row.
Company/Role COMPANY1 COMPANY2 COMPANY3
ROLE1 [X] [] []
ROLE2 [] [] [X]
ROLE3 [] [] []
The added complexity is being able to handle postback. My view model structure is currently..
public class RequestViewModel
{
public Guid Id { get; set; }
public List<CompanyAccessViewModel> CompanyAccessViewModels { get; set; }
}
public class CompanyAccessViewModel
{
public int Company { get; set; }
public Guid Id { get; set; }
public Guid RequestId { get; set; }
public List<Company> ListCompanies { get; set; }
public List<Role> ListRoles { get; set; }
public List<CompanyAccessRoleViewModel> CompanyAccessRoleViewModels { get; set; }
}
public class CompanyAccessRoleViewModel
{
public Guid AccessRequirementId { get; set; }
public Guid Id { get; set; }
public string Role { get; set; }
}
ListCompanies is the list of all the companies.
ListRoles is a list of all the roles.
As always, start with a view model(s) to represent what you want to display/edit.
public class RoleVM
{
public int ID { get; set; }
public string Name { get; set; }
public List<CompanyVM> Companies { get; set; }
}
public class CompanyVM
{
public int ID { get; set; }
public string Name { get; set; }
public bool IsSelected { get; set; }
}
and in the GET method
[HttpGet]
public ActionResult Index()
{
IEnumerable<Role> roles = db.Roles;
IEnumerable<Company> companies = db.Companies;
List<RoleVM> model = roles.Select(x => new RoleVM()
{
ID = x.ID,
Name = x.Name,
Companies = companies.Select(y => new CompanyVM()
{
ID = y.ID,
Name = y.Name
}).ToList()
}).ToList();
// For editing existing roles, set the IsSelected property
// of the respective CompanyVM to true
return View(model);
}
and the view
#model List<RoleVM>
#using (Html.BeginForm())
{
<table>
<thead>
<tr>
<th>Company/Role</th>
#foreach(var company in Model.FirstOrDefault().Companies)
{
<th>#company.Name</th>
}
</tr>
</thead>
<tbody>
#for (int i = 0; i < Model.Count; i++)
{
<tr>
<td>
#Model[i].Name
#Html.HiddenFor(m => m[i].ID)
#Html.HiddenFor(m => m[i].Name)
</td>
#for (int j = 0; j < Model[i].Companies.Count; j++)
{
<td>
#Html.HiddenFor(m => m[i].Companies[j].ID)
#Html.HiddenFor(m => m[i].Companies[j].Name)
#Html.CheckBoxFor(m => m[i].Companies[j].IsSelected)
</td>
}
</tr>
}
</tbody>
</table>
<button type="submit">Save</button>
}
which will the post to
[HttpPost]
public ActionResult Index(List<RoleVM> model)
{
// To get the companies for each role
foreach (var role in model)
{
var selectedCompanies = role.Companies.Where(x => x.IsSelected);
Note that using nested foreach loops would never have bound correctly when submitting your form (you need to use for loops). If you want to use EditorTemplates (your properties can be IEnumerable<T> rather that IList<T>, then create a partial in /Views/Shared/EditorTemplates/RoleVM.cshtml
#model RoleVM
<tr>
<td>
#Model.Name
#Html.HiddenFor(m => m.ID)
#Html.HiddenFor(m => m.Name)
</td>
#Html.EditorFor(m => m.Companies)
</tr>
and another for /Views/Shared/EditorTemplates/CompanyVM.cshtml
#model CompanyVM
<td>
#Html.HiddenFor(m => m.ID)
#Html.HiddenFor(m => m.Name)
#Html.CheckBoxFor(m => m.IsSelected)
</td>
and the main view would be
#model List<RoleVM>
.... // as above
<tbody>
#Html.EditorFor(m => m)
</tbody>

ASP MVC Nested Models

I need a view that displays rows of header-detail info. For a trivial case I set up a Course-Student tiny database with 4 simple tables. The Courses and Students tables are linked with a Section table which also has a student grade in it. Also, the Student table is owned by a Student Type Table. There are helper classes to hold the list of "header" data for the course and a "detail" list for each student who takes that class.
namespace SchoolA.Models
{
public class CourseInfo2
{
public int CourseID { get; set; }
public int CourseNumber { get; set; }
public string CourseName { get; set; }
public IEnumerable<CourseSectionList> CourseStudentList { get; set; }
}
}
namespace SchoolA.Models
{
public class CourseSectionList
{
public string Student { get; set; }
public string Type { get; set; }
public string Grade { get; set; }
}
}
The controller is:
public ActionResult Courselisting()
{
List<CourseInfo2> courseInfo2 = new List<CourseInfo2>();
List<CourseSectionList> courseSectionList = new List<CourseSectionList>();
var Cquery = from c in db.Courses select c;
foreach (var item in Cquery)
{
Course course = db.Courses.Find(item.CourseID); // first find the selected course
// get the sections
foreach (var s in query) // go through each section
{
// get the section data
courseSectionList.Add(new CourseSectionList
{
Student = student.StudentName,
Type = studentType.StudentTypeName,
Grade = s.SectionStudentGrade
});
} // end of section loop
courseInfo2.Add(new CourseInfo2
{
CourseID = course.CourseID,
CourseNumber = course.CourseNumber,
CourseName = course.CourseName,
CourseStudentList = courseSectionList
});
} // end of Course loop
return View(courseInfo2); // Course List and Section list for each course
}
The View is:
#model SchoolA.Models.CourseInfo2
#* doesn't work either: model List<SchoolA.Models.CourseInfo2>*#
<div>
<table>
<tr><th>ID</th> <th>Number</th> <th>Course</th></tr>
#foreach (var CourseInfo2 in Model)
{
<tr>
<td>
#CourseInfo2.CourseID
</td>
<td>
#CourseInfo2.CourseNumber
</td>
<td>
#CourseInfo2.CourseName
</td>
<td>
<table class="table">
<tr><th>Student</th> <th>Type</th><th>Grade</th></tr>
#foreach (var s in Model.CourseStudentList)
{
<tr>
<td>
#s.Student
</td>
<td>
#s.Type
</td>
<td>
#s.Grade
</td>
</tr>
}
</table>
</td>
</tr>
}
</table>
</div>
The problem is that I get a variety of errors as I try to pass these two models to the view. In the code as shown above I get this error:
CS1579: foreach statement cannot operate on variables of type 'SchoolA.Models.CourseInfo2' because 'SchoolA.Models.CourseInfo2' does not contain a public definition for 'GetEnumerator'
I've tried a number of variations for passing the models but always run into one error other the other that prevents both models from working in the view. I should note that I tested each part of the view independently and the controller code works fine to deliver the correct data to the view. However, I can't combine the two.
The problem seems to be the way I create instances of the models an how they are passed to the view. What am I doing wrong?
You're passing your view a List<SchoolA.Models.CourseInfo2>, but the view expects a single SchoolA.Models.CourseInfo2.
Change your #model declaration to IEnumerable<SchoolA.Models.CourseInfo2>.
Then change your foreach loops.
Change the first loop to foreach (var courseInfo in Model)
Change the inner loop to foreach (var s in courseInfo.CourseStudentList)
You are passing a model which is list of object, while in view you have single object.
Change your view model bind as below:
#model List<SchoolA.Models.CourseInfo2>
Problem: I have to edit Level2Name (by UI it's a textbox inside the child grid).
I'm able to edit Level1name (parent grid text field) and able to get value in my controller.
Question: How do I able to edit the nested textbox.
What I've tried.
Code:
Model
public class Level0
{
public Level0()
{
Level1= new List<Level1>();
}
public int? ID{ get; set; }
public int? NameText{ get; set; }
public List<Level1> lev1{ get; set; }
}
public class Level1
{
public Level1()
{
Level2= new List<Level2>();
}
public int Lev1ID {get;set;}
public string Level1name{ get; set; }
public List<Level2> level2{ get; set; }
}
public class Level2
{
public string Level2_ID { get; set; }
public string Level2Name{ get; set; }
}
UI Code
#for (int i = 0; i < Model.Level1.Count; i++)
{
#Html.HiddenFor(modelItem => Model.Floors[i].Lev1ID )
#for (int j = 0; j < Model.Level1[i].Level2.Count; j++)
{
#Html.HiddenFor(m => m.Level1[i].Level2[j].OP)
#Html.TextBoxFor(m => m.Level1[i].Level2[j].Level2Name, new { #class = "form-control" })
}
}

Using 2 models in one view in ASP.NET MVC 5

I am new to ASP.NET MVC and I am kindly asking you to help me with this problem:
I have 2 models - Delegation:
public int idDelegation { get; set; }
public string Delegation_Name { get; set; }
public string Employee_Name { get; set; }
and Project:
public int idProject { get; set; }
public string Project_System_Name { get; set; }
public string Project_System_ID { get; set; }
I want to display in a view a list of current delegations and projects, with the Edit/Details/Delete options for each one.
I created a ViewModel DelegationProject:
public class DelegationProject
{
public IEnumerable<Delegation> delegations { get; set; }
public IEnumerable<Project> projects { get; set; }
}
In my Index view I have:
#model IEnumerable<....ViewModel.DelegationProject>
<table class="table">
<tr>
<th>#Html.DisplayNameFor(model => model.delegations.Employee_Name</th>
<th>#Html.DisplayNameFor(model => model.delegations.Delegation_Name</th>
</tr>
#foreach (var item in Model)
{
<tr>
<td>#Html.DisplayFor(itemModel => item.delegations.Employee_Name)</td>
<td>#Html.DisplayFor(itemModel => item.delegations.Delegation_Name</td>
<td>
#Html.ActionLink("Edit", "Edit", new { x => x.idDelegation }) |
#Html.ActionLink("Details", "Details", new { x => x.idDelegation }) |
#Html.ActionLink("Delete", "Delete", new { x => x.idDelegation })
</td>
</tr>
}
</table>
When I run the application, I get these error messages:
Description: An error occurred during the compilation of a resource required to service this request. Please review the following specific error details and modify your source code appropriately.
Compiler Error Message: CS1061: 'System.Collections.Generic.IEnumerable' does not contain a definition for 'Employee_Name' and no extension method 'Employee_Name' accepting a first argument of type 'System.Collections.Generic.IEnumerable' could be found (are you missing a using directive or an assembly reference?)
I tried different things (like List<> or Tuple) from stackoverflow topics and other sites posts, but I wasn't able to use to models in the same view and iterate through them.
I managed to find a solution for this problem.
The ViewModel DelegationProject remained the same, in my controller for Index action I have:
public ActionResult Index()
{
DelegationProject viewModel = new DelegationProject();
viewModel.delegations = GetDelegations();
viewModel.projects = GetProjects();
return View(viewModel);
}
And I created two methods in the respective controller - GetDelegations() and GetProjects():
public List<Delegation> GetDelegations()
{
var deleg = db.Delegation.Include(d => d.Project);
var list = new List<Delegation>(deleg).ToList();
return list;
}
public List<Project> GetProjects()
{
var projects = db.Project.Include(p => p.Country);
var list = new List<Project>(projects);
return list;
}
My View looks like this:
#model .......ViewModel.DelegationProject
#foreach (var item in Model.delegations)
{
<tr>
<td>
#Html.DisplayFor(itemModel => item.Employee_Name)
</td>
<td>
#Html.DisplayFor(itemModel => item.Delegation_Name)
</td>
</tr>
}
Hope this could be of any help to somebody.

ASP MVC3 Error - There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key

I've researched this a bit and haven't found an answer that quite deals with a similar situation or MVC3. In the ViewModel I'm using I have a Lists of a separate model (List<AgentId> which is a list of the AgentId model).
In the Create page for this controller, I need an input section for 5 items to be added to this list. However, before the page even load, I receive this error message:
There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'BankListAgentId[0].StateCode'.
Here is the ViewModel I am using:
public class BankListViewModel
{
public int ID { get; set; }
public string ContentTypeID1 { get; set; }
public string CreatedBy { get; set; }
public string MANonresBizNY { get; set; }
public string LastChangeOperator { get; set; }
public Nullable<System.DateTime> LastChangeDate { get; set; }
public List<BankListAgentId> BankListAgentId { get; set; }
public List<BankListStateCode> BankListStateCode { get; set; }
}
And here is the section of the view that's having the issues:
<fieldset>
<legend>Stat(s) Fixed</legend>
<table>
<th>State Code</th>
<th>Agent ID</th>
<th></th>
<tr>
<td>
#Html.DropDownListFor(model => model.BankListAgentId[0].StateCode,
(SelectList)ViewBag.StateCode, " ")
</td>
<td>
#Html.EditorFor(model => model.BankListAgentId[0].AgentId)
#Html.ValidationMessageFor(model => model.BankListAgentId[0].AgentId)
</td>
</tr>
<tr>
<td>
#Html.DropDownListFor(model => model.BankListAgentId[1].StateCode,
(SelectList)ViewBag.StateCode, " ")
</td>
<td>
#Html.EditorFor(model => model.BankListAgentId[1].AgentId)
#Html.ValidationMessageFor(model => model.BankListAgentId[1].AgentId)
</td>
<td id="plus2" class="more" onclick="MoreCompanies('3');">+</td>
</tr>
</table>
</fieldset>
I believe #Html.DropDownListFor() is expecting an IEnumerable<SelectListItem>, you can bind it the following way:
In your ViewModel:
public class BankListViewModel
{
public string StateCode { get; set; }
[Display(Name = "State Code")]
public IEnumerable<SelectListItem> BankListStateCode { get; set; }
// ... other properties here
}
In your Controller load the data:
[HttpGet]
public ActionResult Create()
{
var model = new BankListViewModel()
{
// load the values from a datasource of your choice, this one here is manual ...
BankListStateCode = new List<SelectListItem>
{
new SelectListItem
{
Selected = false,
Text ="Oh well...",
Value="1"
}
}
};
return View("Create", model);
}
And then in the View bind it:
#Html.LabelFor(model => model.BankListStateCode)
#Html.DropDownListFor(model => model.StateCode, Model.BankListStateCode)
I hope this helps. Let me know if you nee clarifications.
This error wound up being thrown because the ViewBag element I was using had the same name as one of the list item properties.
The solution was to change ViewBag.StateCode to ViewBag.StateCodeList.

ViewModel collection property lost values after posting back to controller action in MVC 3

I have my view models :
public class POReceiptViewModel
{
public virtual int PONumber { get; set; }
public virtual string VendorCode { get; set; }
public virtual IList<POReceiptItemViewModel> POReceiptItems { get; set; }
public POReceiptViewModel()
{
POReceiptItems = new List<POReceiptItemViewModel>();
}
}
public class POReceiptItemViewModel
{
public virtual string ItemCode { get; set; }
public virtual string ItemDesription { get; set; }
public virtual decimal OrderedQuantity { get; set; }
public virtual decimal ReceivedQuantity { get; set; }
public virtual DateTime ReceivedDate { get; set; }
public POReceiptItemViewModel()
{
ReceivedDate = DateTime.Now;
}
}
Then my controller has two actions, one get and one post:
public ActionResult CreatePOReceipt(int poNumber)
{
PurchaseOrder po = PurchasingService.GetPurchaseOrder(poNumber);
POReceiptViewModel poReceiptViewModel = ModelBuilder.POToPOReceiptViewModel(po);
return View("CreatePOReceipt", poReceiptViewModel);
}
[HttpPost]
public ActionResult CreatePOReceipt(POReceiptViewModel poReceiptViewModel)
{
// Here the problem goes. The items in the poReceiptViewModel.POReceiptItems has lost. the count became zero.
return View("Index");
}
And in my View, I can display the model properly and by using #Html.HiddenFor<> I can persist view model data as I wanted to. But not on the List<> navigation property.
#model POReceiptViewModel
#using (Html.BeginForm())
{
<fieldset>
<legend>Purchase Order</legend>
<label>For PO # :</label>
#Html.HiddenFor(m => m.PONumber)
#Html.DisplayTextFor(m => m.PONumber)
<label>Vendor Code :</label>
#Html.HiddenFor(m => m.VendorCode)
#Html.DisplayTextFor(m => m.VendorCode)
</fieldset>
<fieldset>
<legend>Received Items</legend>
<table class="tbl" id="tbl">
<thead>
<tr>
<th>Item Code</th><th>Item Description</th><th>OrderedQuantity</th><th>Received Quantity</th><th>Received Date</th>
</tr>
</thead>
<tbody>
#Html.HiddenFor(m => m.POReceiptItems) // I'm not really sure if this is valid
#if (Model.POReceiptItems.Count > 0)
{
foreach (var item in Model.POReceiptItems)
{
<tr>
<td>#Html.DisplayTextFor(i => item.ItemCode)</td>#Html.HiddenFor(i => item.ItemCode)
<td>#Html.DisplayTextFor(i => item.ItemDesription)</td>#Html.HiddenFor(i => item.ItemDesription)
<td>#Html.DisplayTextFor(i => item.OrderedQuantity)</td>#Html.HiddenFor(i => item.OrderedQuantity)
<td>#Html.TextBoxFor(i => item.ReceivedQuantity)</td>
<td>#Html.TextBoxFor(i => item.ReceivedDate)</td>
</tr>
}
}
</tbody>
</table>
</fieldset>
<input type="submit" name="Received" value="Received" />
}
PROBLEM:
POReceiptItems lost when the form submitted. As much as possible I don't want to use TempData["POReceiptItems"] = Model.POReceiptItems but even if I use it, the value entered into ReceivedQuantity and ReceivedDate are not save into the TempData.
Thanks in advance!
try
#for (int i = 0; i < Model.POReceiptItems.Count(); i++)
{
<tr>
<td>#Html.DisplayTextFor(m => m.POReceiptItems[i].ItemCode)</td>#Html.HiddenFor(m => m.POReceiptItems[i].ItemCode)
<td>#Html.DisplayTextFor(m => m.POReceiptItems[i].ItemDesription)</td>#Html.HiddenFor(m => m.POReceiptItems.ItemDesription) <td>#Html.DisplayTextFor(m => m.POReceiptItems[i].OrderedQuantity)</td>#Html.HiddenFor(m => m.POReceiptItems[i].OrderedQuantity)
<td>#Html.TextBoxFor(m => m.POReceiptItems[i].ReceivedQuantity)</td>
<td>#Html.TextBoxFor(m => m.POReceiptItems[i].ReceivedDate)</td>
</tr>
}
also read this blog post to understand how model binding to a list works
You lose your list because MVC don't handle the List the way you think.
You should use BeginCollectionItem look at this post
I had a similar problem, the "List" attribute returned without values(count = 0), I tried different ways and answers and nither works.
Then I tried by myself and now it is working, this is my solution:
I send an object with some normal attributes and a "List", after that I used the normal attributes and my "list" in a For.
In my controller (Post ActionResult), in the parameters section I added two parameters, my original object and my "List" as second parameter and it works!!!
I hope this helps you and others with similar problems.

Resources