ViewModel - Null in the HttpPost Method

I am using ASP.NET MVC 4 and I created these ViewModels:

public class NotificationViewModel { public string GroupDesc { get; set; } public bool AM { get; set; } public bool PM { get; set; } public int MaxNotif { get; set; } } public class SettingsViewModel { public List<NotificationViewModel> ListNotification { get; set; } public SettingsViewModel() { ListNotification = new List<NotificationViewModel>(); } } 

My view:

 @model PortailT2A.Models.SettingsViewModel @{ ViewBag.Title = "Preferences"; Layout = "~/Views/Shared/_LayoutAdmin.cshtml"; } <h2>Preferences</h2> @using(Html.BeginForm("Preferences", "Administrateur", FormMethod.Post)) { <table id="settingsTable"> <tr> <th>Groupe</th> <th></th> <th>AM</th> <th>PM</th> <th>Limite de notifications</th> </tr> @for (int i = 0; i < Model.ListNotification.Count(); i++ ) { var notif = Model.ListNotification[i]; <tr> <td>@notif.GroupDesc </td> <td>Heure de notification</td> <td>@Html.CheckBoxFor(u => notif.AM) </td> <td>@Html.CheckBoxFor(u => notif.PM) </td> <td>@Html.TextBoxFor(u => notif.MaxNotif)</td> </tr> <tr/> } </table> <input type ="submit" value="Sauvegarder" /> } 

My HttpGet method populates my ViewModel and returns it.

  [HttpGet] public ActionResult Preferences(long idUser) { context = new MainDatabaseEntities(); List<NotificationViewModel> notifications = new List<NotificationViewModel>(); SettingsViewModel settings = new SettingsViewModel(); //Population... return View(settings); } 

However, when I want to save the changes, I have a ViewModel that is null, and I don't understand why. Any ideas guys?

EDIT : my publishing method:

  [HttpPost] public ActionResult Preferences(SettingsViewModel sm) { //since here my ViewModel is null context = new MainDatabaseEntities(); Utilisateur user = (from u in context.Utilisateurs where u.Username == User.Identity.Name select u).FirstOrDefault(); //operations... } 

HTML generated:

 <tr> <td>Groupe B </td> <td>Heure de notification</td> <td><input id="notif_AM" name="notif.AM" type="checkbox" value="true" /><input name="notif.AM" type="hidden" value="false" /> </td> <td><input checked="checked" id="notif_PM" name="notif.PM" type="checkbox" value="true" /><input name="notif.PM" type="hidden" value="false" /> </td> <td><input id="notif_MaxNotif" name="notif.MaxNotif" type="text" value="10" /></td> </tr> 
+6
source share
5 answers

List<T> can be difficult to model, as it depends heavily on indexed keys. Helpers should know the index, but by assigning notif in your for loop, they lose the link. Instead, try the following:

 @for (int i = 0; i < Model.ListNotification.Count(); i++ ) { var notif = Model.ListNotification[i]; <tr> <td>@notif.GroupDesc </td> <td>Heure de notification</td> <td>@Html.CheckBoxFor(u => u.ListNotification[i].AM) </td> <td>@Html.CheckBoxFor(u => u.ListNotification[i].PM) </td> <td>@Html.TextBoxFor(u => u.ListNotification[i].MaxNotif)</td> </tr> <tr/> } 

Which should then provide you with something like:

 <tr> <td>Groupe B </td> <td>Heure de notification</td> <td> <input id="ListNotification[0]_AM" name="ListNotification[0].AM" type="checkbox" value="true" /> <input name="ListNotification[0].AM" type="hidden" value="false" /> </td> <td> <input checked="checked" id="ListNotification[0]_PM" name="ListNotification[0].PM" type="checkbox" value="true" /> <input name="ListNotification[0].PM" type="hidden" value="false" /> </td> <td> <input id="ListNotification[0]_MaxNotif" name="ListNotification[0].MaxNotif" type="text" value="10" /> </td> </tr> 

Also, be sure to check ModelState.IsValid in your published action to make sure the model has been linked correctly. If not, you should see a list of errors in ModelState , which will give you some idea of โ€‹โ€‹where it might fail.

Also, I donโ€™t see you dropping GroupDesc anywhere (other than output). If necessary for the incoming model, you can use @Html.HiddenFor(x => x.ListNotifications[i].GroupDesc) .

+6
source

You are not building your HTML correctly. What is sent back will not have the paths that the connecting device expects.

Consider replacing this:

 @for (int i = 0; i < Model.ListNotification.Count(); i++ ) { var notif = Model.ListNotification[i]; <tr> <td>@notif.GroupDesc </td> <td>Heure de notification</td> <td>@Html.CheckBoxFor(u => notif.AM) </td> <td>@Html.CheckBoxFor(u => notif.PM) </td> <td>@Html.TextBoxFor(u => notif.MaxNotif)</td> </tr> <tr/> } 

with this:

 @Html.DisplayModelFor(m => m.ListNotification) 

and add a template like this to /Views/{YourController}/{YourAction}/EditorTemplates/NotificationViewModel.cshtml

 @model NotificationViewModel <tr> <td>@Model.GroupDesc</td> <td>Heure de notification</td> <td>@Html.CheckBoxFor(m => m.AM)</td> <td>@Html.CheckBoxFor(m => m.PM)</td> <td>@Html.TextBoxFor(m => m.MaxNotif)</td> </tr> 
+4
source

My first suggestion was to try to add some random property to my SettingValueModel parameter and add it to the form as hidden.

Sort of

  public class SettingsViewModel { public List<NotificationViewModel> ListNotification { get; set; } public string TestValue { get; set; } public SettingsViewModel() { ListNotification = new List<NotificationViewModel>(); TestValue = "Test"; } } 

Then, in your opinion, add

 @Html.HiddenFor(s=> s.TestValue) 

When you submit your form, check to see if the SettingsViewModel parameter is null. If the problem is only with ListNotification serialization, then you can get an object with TestValue from "Test" and "Not List List Notifications". If so, at least you know the problem is ListNotifications.

Also try changing the for loop to

  @for (int i = 0; i < Model.ListNotification.Count(); i++ ) { <tr> <td>@Model.ListNotification[i].GroupDesc </td> <td>Heure de notification</td> <td>@Html.CheckBoxFor(u => u.ListNotification[i].AM) </td> <td>@Html.CheckBoxFor(u => u.ListNotification[i].PM) </td> <td>@Html.TextBoxFor(u => u.ListNotification[i].MaxNotif)</td> 

Also, I don't think that FormMethod.Post is required in the form definition. Try it all. If none of them helps, I can only assume that your PC is chasing =)

+2
source

In my case, I had my setters as internal in my model model definition for some strange reason, so the binding could not be set and saved:

 public int PaymentType { get; internal set; } 
0
source

Are you using the correct model type in the POST action?

 [HttpPost] public ActionResult Preferences(PortailT2A.Models.SettingsViewModel model) { //... } 
-1
source

All Articles