【问题标题】:ViewModel is Null in HttpPost methodViewModel 在 HttpPost 方法中为 Null
【发布时间】:2014-05-08 00:41:54
【问题描述】:

我正在使用 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);
    }

但是,当我想保存更改时,我得到了一个为空的 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>

【问题讨论】:

  • 请同时附上您的后期操作代码
  • 我们能看到一个为通知生成的 HTML 样本(可能是一个项目的价值)吗?有些东西告诉我它没有引用ListNotificaton[0].AM[您在for 中使用的快捷方式很可能是罪魁祸首,但如果没有生成的 HTML 则无法确定]
  • @JeremyCook,给你。
  • @BradChristie:完成了!

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


【解决方案1】:

就我而言,出于某种奇怪的原因,我在视图模型定义中将设置器设置为内部,因此无法设置和存储绑定:

public int PaymentType { get; internal set; }

【讨论】:

    【解决方案2】:

    List&lt;T&gt; 在模型绑定时可能会很棘手,因为它严重依赖索引键。帮助者需要知道索引,但是通过在你的 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 =&gt; x.ListNotifications[i].GroupDesc)

    【讨论】:

      【解决方案3】:

      您没有正确构建 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>
      

      【讨论】:

      • +1。虽然需要做更多的工作,但模板系统非常值得。一开始可能会有点混乱,但一旦你掌握了窍门,很多绑定问题就会消失。
      【解决方案4】:

      我的第一个建议是尝试向 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”且 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 在表单定义中是必需的。尝试所有这些事情。如果它们都没有帮助,那么我只能假设您的 PC 闹鬼 =)

      【讨论】:

        【解决方案5】:

        在 POST 操作中,您是否使用正确类型的模型?

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

        【讨论】:

        • 是的,我使用了正确的模型类型,但感谢您的建议。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2020-06-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多