ViewModel在HttpPost方法中是Null

时间:2014-03-28 13:52:29

标签: c# asp.net-mvc entity-framework viewmodel

我使用ASP.NET MVC 4并构建了这些ViewModel:

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>();
    }
}

我的观点:

@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" />

}

我的HttpGet方法填充我的ViewModel并返回它。

    [HttpGet]
    public ActionResult Preferences(long idUser)
    {
        context = new MainDatabaseEntities();

        List<NotificationViewModel> notifications = new List<NotificationViewModel>();

        SettingsViewModel settings = new SettingsViewModel();

        //Population...

        return View(settings);
    }

但是,当我想保存更改时,我得到了一个nullM的ViewModel,我不明白为什么。任何想法的人?

编辑:我的帖子方法:

            [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生成:

<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>

5 个答案:

答案 0 :(得分:6)

模型绑定时,

List<T>可能很棘手,因为它严重依赖于索引键。帮助者需要知道索引,但是通过在for循环中分配notif,他们将丢失引用。相反,尝试以下内容:

@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/>
}

然后应该为您提供如下内容:

<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>

此外,请务必检查已发布操作中的ModelState.IsValid以确认模型已正确绑定。如果没有,您应该会在ModelState中看到一个错误列表,它会告诉您哪些错误可能会失败。

另外,我没有看到你将GroupDesc转储到任何地方(输出除外)。如果在传入的模型上有必要,您可以考虑使用@Html.HiddenFor(x => x.ListNotifications[i].GroupDesc)

答案 1 :(得分:4)

您没有正确构建HTML。回发的内容将没有模型绑定器所期望的路径。

考虑将其替换为:

@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/>
}

用这个:

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

并将此类模板添加到/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>

答案 2 :(得分:2)

我的第一个建议是尝试向您的SettingValueModel添加一些随机属性,并将其作为隐藏添加到表单中。

这样的东西
 public class SettingsViewModel
 {
  public List<NotificationViewModel> ListNotification { get; set; }
  public string TestValue { get; set; }

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

然后在您的视图中添加

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

提交表单时,请检查SettingsViewModel是否为空。如果问题只出现在ListNotification序列化中,那么最终可能会得到一个TestValue为“Test”且为null List Notifications的对象。如果是这种情况,至少你知道问题是ListNotifications。

还可以尝试将for循环更改为此

  @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>

此外,我不认为表单定义中需要FormMethod.Post。尝试所有这些事情。如果它们都没有帮助,那么我只能假设你的电脑被困扰=)

答案 3 :(得分:0)

在我的情况下,由于某些奇怪的原因,我在我的视图模型定义中将我的setter作为内部设置,因此无法设置和存储绑定:

friends.address = friends.address.replace('st','ln');

答案 4 :(得分:-1)

在POST操作中,您使用正确的模型吗?

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