MVC adding table row with binding on a complex viewmodel - c#

In my view model, there is a list of element which contains a table of text inputs.
View model > List of element > Table > lots of text inputs
All of this is generated in the view via EditorTemplates.
Everything is bound perfectly to the view when it load (MVC is creating the right IDs and Names of each input. Now I want to add and delete rows and have the binding updated. This means, that all the right numbers are updated in the IDs and Name.
I have an idea of how to do it with pure JavaScript, but that would be very dirty and a pain to update when things change. I would like to do it with an HTML helpers or a model binder but haven't found a way yet!
Anyone have an idea of how to do that?
EDIT : apparently I have more chance to get answered if I post lots of code detail... but in this complex case, that's going to be long, so hang on!
Here is the view model. (Keep in mind that this code is a dumbed down version)
public class MVCViewModel
{
public List<ActivityElement> ActivityElementList { get; set; }
}
public abstract class ActivityElement
{
}
public class Step : ActivityElement
{
public Step()
{
this.Id = Guid.NewGuid();
this.Label = "Basic Step";
}
public Step(string label, AbstractInput input)
: this()
{
this.Label = label;
this.Input = input;
}
public Guid Id { get; set; }
public string Label { get; set; }
public AbstractInput Input { get; set; }
}
public abstract class AbstractInput
{
public object Value { get; set; }
}
public class GridInput : AbstractInput
{
public List<GridCell> Headerlist { get; set; }
public List<GridRow> RowList { get; set; }
}
public class GridRow
{
public List<GridCell> CellList { get; set; }
}
public class GridCell
{
public string ColumnName { get; set; }
public AbstractInput Input { get; set; }
}
public class TextInput: AbstractInput
{
public TextInput(string value)
{
this.Value = value;
}
}
Alright! If somehow you are still with me, that's good! I have put them in the order that they will be used in this particular case.
To dumb this down, the view model contains a list of Step. The first step contains a GridInput as his AbstractInput property. That grid contains rows and each rows contains cells. For this case, let say each cell contains a TextInput as his AbstractInput.
Now, on the view, when this is displayed with EditorTemplates and HtmlHelpers, all the IDs and Names of the inputs are good (therefor the binding is good), as shown here in this HTML output :
<td>
<input id="ActivityElementList_0__Input_RowList_0__CellList_0__Input_ModelType" name="ActivityElementList[0].Input.RowList[0].CellList[0].Input.ModelType" type="hidden" value="knockout_binding_prototype.Models.TextInput">
<input id="ActivityElementList_0__Input_RowList_0__CellList_0__Input_Value" name="ActivityElementList[0].Input.RowList[0].CellList[0].Input.Value" type="text" value="cell 1 row 1">
</td>
<td>
<input id="ActivityElementList_0__Input_RowList_0__CellList_1__Input_ModelType" name="ActivityElementList[0].Input.RowList[0].CellList[1].Input.ModelType" type="hidden" value="knockout_binding_prototype.Models.TextInput">
<input id="ActivityElementList_0__Input_RowList_0__CellList_1__Input_Value" name="ActivityElementList[0].Input.RowList[0].CellList[1].Input.Value" type="text" value="cell 2 row 1">
</td>
What I am trying to do here, is to be able to add and delete row to this table. This is fairly easy... The hard part is making sure all the binding (IDs and Names) are still good. In the case of this particular HTML output, if I delete the first row, I need the IDs and Names of the second row, to become equivalent to the first row IDs and Name.
I have been trying to find the most generic way to do it, and to try and make it JavaScript less as possible. All ideas will be pondered, so don't afraid to say something!
EDIT 2 : OK, as far as deleting rows go, I decided to just hide the delete row and flag it as deleted, so all the biding remains good. Adding row is simple in JavaScript, but I am searching for a way to do it without JavaScript (or only a little bit).
Here is the update in the view model for the delete flag.
public class GridRow
{
public GridRow()
{
IsDeleted = false;
}
public List<GridCell> CellList { get; set; }
public bool IsDeleted { get; set; }
}

Try this way without buggy JS html modifications. You can do delete this way as well. Also you can decide if you want to save the model on every add/delete call or save it after all changes.
Models:
public class SampleModel
{
public List<ItemModel> Items { get; set; }
public SampleModel()
{
Items = new List<ItemModel>();
}
}
public class ItemModel
{
public int Id { get; set; }
public string Name { get; set; }
}
Controller:
[HttpPost]
public ActionResult Add(SampleModel model)
{
model.Items.Add(new ItemModel { Name = "New Item" });
return PartialView("Items");
}
public ActionResult Index()
{
var model = new SampleModel(); // Or get model
return View(model);
}
[HttpPost]
public ActionResult Index(SampleModel model)
{
// Save model to DB
return RedirectToAction("Index");
}
Index.cshtml
#model SampleModel
#using (Html.BeginForm())
{
<div id="container">
#Html.Partial("Items", Model)
</div>
<a id="add" href="javascript:void(0);">Add</a>
<button type="submit">Save</button>
}
<script src="jquery.js"></script>
<script type="text/javascript">
$(function () {
$('#add').on('click', function () {
$.post('#Url.Action("Add")', $('form').serializeModel(), function(html) {
$('#container').html(html);
});
});
});
$.fn.serializeModel = function () {
var model = {};
$(this).serializeArray().map(function (item) {
model[item.name] = item.value;
});
return model;
};
</script>
Items.cshtml:
#model SampleModel
<table>
#for (var i = 0; i < Model.Items.Count; i++)
{
<tr>
<td>
#Html.HiddenFor(m => Model.Items[i].Id)
#Html.TextBoxFor(m => Model.Items[i].Name)
</td>
</tr>
}
</table>

Related

.NET MVC showing a variable value

I have the this set up and am trying to get lkup_1_txt to show in the page as either text or the selected item in the dropdown.
I have tried the following
#lkup1
and
#Html.DisplayFor(modelItem => item.lkup1)
and
#foreach (var item in Model)
{#Html.DisplayFor(modelItem => item.lkup1)}
This is my structure -
Model for Look Up Reference drop down selection
public class ListItem
{
public string Value { get; set; }
public string Text { get; set; }
}
public class ModelForDropDown
{
public string SelectedItemText { get; set; }
public List<ListItem> ItemListText { get; set; }
}
public class LkupResultRecord
{
public ModelForDropDown lkup_1_txt { get; set; }
public ModelForDropDown lkup_2_txt { get; set; }
}
Controller for the create new lkup1txt dropdown -
public ActionResult LkupRef_Lkup1()
{
return View(lkuprefdao.getValuesForLkupTxtDropDown());
}
[HttpPost]
public ActionResult LkupRef_Lkup1(string lkup_1_txt)
{ return RedirectToAction("LkupRef_Lkup2", "LkupRef", new
{
lkup_1_txt = lkup_1_txt
});
}
Controller for the create new lkup2txt dropdown -
public ActionResult LkupRef_Lkup2()
{
if (lkuprefdao.IsDataRefreshDowntime() == true) { return RedirectToAction("BadgerWeb_RestrictedAccess", "LkupRef"); }
return View(lkuprefdao.getValuesForLkupTxtDropDown());
}
and the view where I want the lkup_1_txt to display -
#using (Html.BeginForm())
{
<table>
<tr>
<td>lkup_1_txt</td>
<td> #Html.DisplayFor(lkup_1_txt) </td>
</tr>
<tr>
<td> lkup_2_txt </td>
<td>#Html.DropDownList("lkup_2_txt", new SelectList(Model.lkup_2_txt.ItemListText, "Value", "Text"), null, new { style = "width: 650px;" })</td>
</tr>
</table>
}
I
It's all still a bit unclear and doesn't make a great deal of sense, but I think you probably want something like this:
1) define lkup_1_txt as a string in your model, to match with the querystring value you're trying to feed to it. Defining it as a complex type like ModelForDropDown (as you did) doesn't appear to make any sense.
public class LkupResultRecord
{
public string lkup_1_txt { get; set; }
public ModelForDropDown lkup_2_txt { get; set; }
}
2) Add a parameter to allow the LkupRef_Lkup2() action method to receive the input value from the redirect (or from a direct request). Right now it is just ignoring the input. And also modify the action method code so you can add the incoming lookup text to the model before passing it to the view.
public ActionResult LkupRef_Lkup2(string lkup_1_txt)
{
if (lkuprefdao.IsDataRefreshDowntime() == true) { return RedirectToAction("BadgerWeb_RestrictedAccess", "LkupRef"); }
LkupResultRecord model = lkuprefdao.getValuesForLkupTxtDropDown();
model.lkup_1_txt = lkup_1_txt; //add the lookup text to the model
return View(model);
}
3) Modify the view so it can read the lookup text from the model property:
<td>lkup_1_txt</td>
<td> #Html.DisplayFor(m => m.lkup_1_txt) </td>

How to render a model with list of objects in view as a form? [duplicate]

This question already has answers here:
Asp.Net MVC: Why is my view passing NULL models back to my controller?
(2 answers)
Closed 5 years ago.
I need to display a specific form in a view with a model. The model is like that:
This is the final object filled what I need :
public class ObjetTotal
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Numero { get; set; }
public string Value { get; set; }
}
I choose to cut the form into two differents parts :
First a "static" part where the user can put common values for the differents ObjetsTotal.
Second a "variable" part where the user put differents values for the differents ObjetsTotal.
The final aim is that the user doest'n have to type, the same thing for all the objects ObjetTotal.
So, I create other objects (I don't know if it's a good practice) which represents the differents part of the form.
The static part with MainObjet and the variable part with Numbers. I put these two object into an other object "Mix" which contains one "MainObjet" and a list of "Numbers".
public class MainObjet
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
public class Numbers
{
public string Numero { get; set; }
public string Value { get; set; }
}
public class Mix
{
public MainObjet obj { get; set; }
public IEnumerable<Numbers> num { get; set; }
public Mix()
{
obj = new MainObjet();
num = new List<Numbers>();
}
}
Then I want to render the model Mix in a view to have the two parts of the form.
I've try this :
#model App.Models.Mix
#using (Html.BeginForm()) {
#Html.AntiForgeryToken()
#Html.ValidationSummary(true)
<fieldset>
<legend>Mix</legend>
<h3>First Properties</h3>
<div>
#Html.TextBoxFor(model => model.obj.Id);
#Html.TextBoxFor(model => model.obj.Name);
#Html.TextBoxFor(model => model.obj.Description);
</div>
<div>
<table>
#for (int i = 0; i < 5; i++)
{
<tr>
<td>
#Html.TextBoxFor(model => model.num[i].Numero)
</td>
<td>
#Html.TextBoxFor(model => model.num[i].Value)
</td>
</tr>
}
</table>
</div>
<p>
<input type="submit" value="Create" />
</p>
</fieldset>
}
But after the submit I get an object Mix null in this ActionResult :
[HttpPost]
public ActionResult Test(Mix obj)
{
return View();
}
Can you explain me how to do that ? May I'm on a wrong way.
Don't consider the design of the form, and I don't know the right type to put to Numbers, Maybe a simple list be enough for that.
The thing I can see is that you are missing the initialization of your model properties in the parameter-less constructor. You should try to update your model code to be:
public class Mix
{
public MainObjet obj { get; set; }
public IEnumerable<Numbers> num { get; set; }
public Mix()
{
obj = new MainObjet();
num = new List<Numbers>();
}
}
As the model binder will instantiate your model, and it will find obj and num to null and will not be able to post the values back.
Hope this helps you.

Populate drop down in MVC using different View and Controller

I'm creating an internal CMS system. I have a page that retrieves an Item and allows the user to carry our various administrative tasks.
Lets look at the following:
Quote (Page)
Item (Page) - ItemDetails (Partial within Item) - Artwork (partial within ItemDetails)
A user selects a quote. Then views an Item which retrieves an item with associated content. Within an Item, they can select Artwork or any other tabs (partial views also).
The user then has the ability to change values for an internal CMS system. I want to:
Pre-populate several different dropdown lists. (If it helps, I have some pre-formatted select tags, I could re-use, was used in an angular project).
These Dropdown boxes should be pre-loaded with any existing values if found attached to an item.
Have a form with the ability to change the value and update it.
Having just moved to MVC, I'm struggling to nail it, despite scouring for over a day on various guides/tutorials. Just in case you're wondering why I'm wanting to separate the controllers, it's because the project is going to become vast. Architecturally, it makes sense.
Example: Mockup Types is within Artwork. I've used entity framework and I'm retrieving all my MockupTypes successfully.
The first partial:
#Html.Partial(MVC.Item.Views.ViewNames._TabbedItemDetailsPanel, Model.SelectedItem)
SelectedItem viewModel:
public class SelectedItem
{
public ArtworkDetailViewModel ArtworkDetail { get; set; }
//Several others
}
ArtworkDetail contains:
public class ArtworkDetailViewModel : DataViewModel
{
public int? ItemID { get; set; }
public FaceColourViewModel FaceColour { get; set; }
public MockupTypeViewModel MockupType { get; set; }
public ProofingTypeViewModel ProofType { get; set; }
//Others
}
This is brought in by the item controller:
public partial class ItemController : Controller
{
public virtual ActionResult ItemDetail(int itemId)
{
var model = new QuotePageViewModel();
var item = itemViewModelService.GetItemByID(itemId);
model.LiveQuotes = quotesOverviewViewModelService.GetItemsByQuote(item.QuoteID.Value);
model.SelectedItem = item;
return View(model);
}
}
Within the partial posted above, I have a tab for Artwork, which is another separate partial view:
#Html.Partial(MVC.Item.Views._TabbedArtwork, new ViewModels.Artwork.ArtworkAttributesViewModel())
My thinking is the ArtworkAttributesViewModel will have a list of pre-populated models
public class ArtworkAttributesViewModel
{
public IEnumerable<ProofingTypeViewModel> ProofTypes { get; set; }
public IEnumerable<MockupTypeViewModel> MockupTypes { get; set; }
//Others
}
This comes from a separate controller called Artwork.
public partial class ArtworkDetailController : Controller
{
[HttpGet]
public virtual ActionResult GetAttributes()
{
var model = new ArtworkAttributesViewModel();
model = artworkAttributesViewModelService.GetArtworkAttributes();
return View(model);
}
}
Within _TabbedArtwork, I started to create a form:
#model ViewModels.Artwork.ArtworkAttributesViewModel
#using (Html.BeginForm(MVC.ArtworkDetail.ActionNames.Index, MVC.ArtworkDetail.Name, FormMethod.Get))
{
<div class="row">
<div class="col-md-12">
<p><strong></strong> <br />
</div>
<div class="col-md-12">
<div class="row show-grid">
<p class="margin-bottom-zero"><strong>Mockup Types</strong></p>
<div class="col-md-3 col-xs-12">
#Html.DropDownListFor()
<select class="selectpicker"></select>
</div>
</div>
</div>
</div>
}
In summary, I have 2 partials, 2 viewmodels and 2 controllers. How on earth do I bring all of this this together?
Much appreciated.
Edit: Still battling on getting the second controller to send the view to the partial
You can bind the dropdown to the item to be edited and the model to populate it.
public class mainitem() {
public int id { get; set; }
public int type { get; set; }
}
public class type() {
public int id { get; set; }
public string name { get; set; }
}
public class myviewmodel() {
public mainitem item { get; set; }
public List<type> types { get; set; }
}
#Html.DropDownListFor(x => x.item.type,
new SelectList(Model.types, "id", "name"), "-Select-",
new { #class = "form-control" })

Populating nested list object of model based on checkbox selections in ASP.NET MVC

I am relatively new to ASP.NET MVC and I find myself a bit on a stick wicket or rather, in a soup kinda situation. This is a length description so please bear with me. And I'm sorry if this seems a bit long and boring :). So, here's my problem :
This is my model.
public class SocialAccount
{
public int SocialAccountID { get; set; }
public int UserID { get; set; }
public int SocialSiteID { get; set; }
public string SocialAccountUsername { get; set; }
public string SocialAccountUserID { get; set; }
public string OAuthToken { get; set; }
public string Captcha { get; set; }
public string UserCaptchaValue { get; set; }
}
public class SocialSitePost
{
public int PostID { get; set; }
public string PostContent { get; set; }
public string PostAttachments { get; set; }
public List<SocialSite> SelectedSocialSites { get; set; }
public List<SocialAccount> SocialAccount { get; set; }
}
public class SocialSite : Audit
{
public int SocialSiteID { get; set; }
public string SocialSiteName { get; set; }
}
When a user is successfully authenticated, I store some user details in session and redirect to the home page. This is the code for that:
//action method in some Controller
public Login()
{
//Authenticate user
//Get all social account related information
SomeRepository someRepository = new SomeRepository();
List<SocialAccount> socialAccountDetails = someRepository.SomeMethod(user.UserID);
//Add social account related information to session
HttpHelper.StoreInSession("UserDetails", socialAccountDetails);
//redirect to HomePage
return RedirectToAction("HomePage", "Account");
}
In the HomePage action method, I retrieve the user object from session and check the registered social accounts. I also create a list object of SocialSite to maintain a list of all registered social sites. I then pack it in ViewData and send it to the view. This is the code for that:
//action method in some other controller
public ActionResult HomePage()
{
List<SocialSite> allSocialSites = null;
List<SocialAccount> userSocialAccountDetails = HttpHelper.RetrieveFromSession("UserSocialSiteDetails") as List<SocialAccount>;
if (userSocialAccountDetails != null && userSocialAccountDetails.Count != 0)
{
allSocialSites = new List<SocialSite>();
bool hasFacebookAccount = userSocialAccountDetails.Exists(x => x.SocialSiteID == Convert.ToInt32(CommonConstants.SocialSite.Facebook));
if (hasFacebookAccount)
{
allSocialSites.Add(new SocialSite() { SocialSiteID = 1, SocialSiteName = "Facebook" });
}
bool hasTwitterAccount = userSocialAccountDetails.Exists(x => x.SocialSiteID == Convert.ToInt32(CommonConstants.SocialSite.Twitter));
if (hasTwitterAccount)
{
allSocialSites.Add(new SocialSite() { SocialSiteID = 2, SocialSiteName = "Twitter" });
}
}
ViewData["SocialSites"] = allSocialSites;
return View();
}
I don't have a strongly-typed view. What I need to do is post the user response. So I create a form for POSTing. Now within this form, I want to display a checkbox for all the registered social accounts (ViewData would give me this info). So, lets say, if user A registered only a Facebook account, then only 1 checkbox representing Facebook should be visible. If user B registered a Facebook, Twitter and Instagram account, then 3 checkboxes should be visible one representing each of these social accounts. I guess you get the idea. This is my code for that:
#model SocialSitePost
#{
using (Html.BeginForm("ProcesssRequest", "Account", FormMethod.Post))
{
<div class="divProcessRequest">
<br />
<div>
#Html.TextAreaFor(model => model.PostContent)
</div>
<div>
#foreach (var socialSite in ViewData["SocialSites"] as List<SocialSite>)
{
#Html.CheckBox("SocialSiteID", new { value = socialSite.SocialSiteID, #checked = true });
#Html.Label(socialSite.SocialSiteName)
} //Tried this..And am able to display the checkbox
#*#for (int i = 0; i < Model.SelectedSocialSites.Count; i++)
{
#Html.CheckBoxFor("SocialSiteID", new { value = Model.SelectedSocialSites[i].SocialSiteID, #checked = true });
}*# //Tried this too..I know this shouldn't work and rightly so, it doesn't work :)
</div>
<br />
<div>
<input type="submit" id="btnPost" value="Post" />
</div>
</div>
}
}
Enough said!!! Now my real problem:
When the user selects any checkbox, I want to populate the SelectedSocialSites property of the SocialSitePost object. This is the model whose object the form is posting back. I need to be able to access the SelectedSocialSites property in the POST method. This is how my POST method is :
[HttpPost]
public ActionResult ProcessRequest(SocialSitePost post)
{
if (ModelState.IsValid)
{
List<SocialSite> allSocialSites = ViewData["SocialSites"] as List<SocialSite>; //Can't get anything here
int socialSiteNo = post.SelectedSocialSites.SocialSiteID; //This is what I want to be able to do
return View("HomePage");
}
}
Since, I am relatively new to ASP.NET MVC, I'm not really sure if this is the right way of doing this. I did try out a few things like EditorFor, trying to send the SocialSitePost object the first time the view is rendered (I don't want to do this as it doesn't make any logical sense).
Can someone tell me how I can get the SelectedSocialSites property of the SocialSitePost class populated in the POST method based on the checkbox selections made by the user?
Also, can someone tell me if I am doing something wrong here as I haven't found any questions here so far on SO which seem similar to this kind of situation?
The main problem here is that the model is not completely suitable for what needs to be displayed. That is, the format of the model with respect to the view and its representation at the backend is different. Hence, a ViewModel needs to be used here. This is what solved my issue.
These were the ViewModels I ended up designing:
public class SocialSiteViewModel : SocialSite
{
public bool IsSelected { get; set; }
public string SocialSitePostID { get; set; }
}
public class SocialSitePostViewModel : SocialSitePost
{
public List<SocialSiteViewModel> SocialSiteViewModel { get; set; }
}
And then I could easily use them on the view as such:
using (Html.BeginForm("ActionMethodName", "ControllerName", FormMethod.Post))
{
#Html.CheckBoxFor(x => x.SocialSiteViewModel[i].IsSelected)
#Html.HiddenFor(x => x.SocialSiteViewModel[i].SocialSiteID)
#Html.HiddenFor(x => x.SocialSiteViewModel[i].SocialSiteName)
}

MVC Add and remove items from subcollection

I'm having trouble binding data to a collection item's collection (I'm also having trouble wording my problem correctly). Let's just make thing easier on everyone by using an example with psudo models.
Lets say I have the following example models:
public class Month()
{
public int ID { get; set; }
public string Name { get; set; }
public virtual ICollection<Week> Weeks { get; set; }
}
public class Week()
{
public int ID { get; set; }
public int MonthID { get; set; }
public String Name { get; set; }
public virtual ICollection<Day> Days { get; set; }
}
public class Day()
{
public int ID { get; set; }
public String Name { get; set; }
}
...and an example viewmodel:
public class EditMonthViewModel()
{
public Month Month { get; set; }
public List<Week> Weeks { get; set; }
public List<Day> AllDays { get; set; }
}
The purpose of the Edit Action/View is to enable users to edit a month, the weeks assigned to the month, and add and remove days from weeks of a certain month. A view might help.
#model myProject.ViewModels.EditMonthViewModel
//...
#using (Html.BeginForm())
{
//Edit Month Stuff...
#for(int i = 0; i < Model.Weeks.Count(); i++)
{
<h2>#Model.Weeks[i].Name</h2>
#Html.EditorFor(model => Model.Weeks[i].Name)
//loop through all possible days
//Select only days that are assigned to Week[i]
#for(int d = 0; d < Model.AllDays.Count(); d ++)
{
//This is the focus of this question.
//How do you bind the data here?
<input type="checkbox"
name="I have no idea"
#Html.Raw(Model.Weeks[i].Days.Contains(Model.AllDays[d]) ? "checked" : "") />
}
}
}
Controller Action methods
public ActionResult Edit(int id)
{
var viewModel = new EditMonthViewModel();
viewModel.Month = db.Months.Find(id);
viewModel.Weeks = db.Weeks.Where(w => w.MonthID == id).ToList();
viewModel.AllDays = db.Days.ToList();
}
[HttpPost]
public ActionResult Edit(EditMonthViewModel viewModel)
{
var monthToUpdate = db.Months.Find(viewModel.Month.ID);
//...
if(viewModel.Weeks != null)
{
foreach (var week in viewModel.Weeks)
{
var weekToUpdate = monthToUpdate.Weeks.Single(w => w.ID == week.ID);
//...
/*So, I have a collection of weeks that I can grab,
but how do I know what was selected? My viewModel only has a
list of AllDays, not the days selected for Week[i]
*/
}
}
How can I ensure that when I submit the form the selected days will bind to the week?
It looks like the easiest thing to do is to make it a goal for your form to populate a data structure of the type IEnumerable<DayModel>, where DayModel is defined as:
public class DayModel
{
public int WeekId { get; set; }
public int DayId { get; set; }
public bool IsIncluded { get; set; }
}
You could keep your Razor code as is for the most part, but then when it comes to rendering the checkboxes, you can do something like this:
#{
var modelIdx = 0;
}
// ...
<input type="hidden" name="days[#modelIdx].WeekId" value="#Model.Weeks[i].Id" />
<input type="hidden" name="days[#modelIdx].DayId" value="#Model.AllDays[d].Id" />
<input type="checkbox" name="days[#modelIdx].IsIncluded" value="#(Model.Weeks[i].Days.Contains(Model.AllDays[d]) ? "checked" : "")" />
#{ modelIdx++; }
Then, your controller action you post to could have this signature:
[HttpPost]
public ActionResult Edit(IEnumerable<DayModel> days)
{
//...
}
Something that helps me is to never confuse view models, which should only be used for the model for views (GET actions generally) and non-view models (what we call plain models). Avoid having your POST actions try to bind to view models, and it will simplify your life greatly.

Categories

Resources