简体   繁体   English

发布后,MVC4复杂类型模型为空

[英]MVC4 Complex Type Model is null after post

This is my model 这是我的模特

public class AdministrationModel
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string EmailAddress { get; set; }
  public bool IsApproved { get; set; }
}

This is my controller 这是我的控制器

public ActionResult GetTabContent(string id)
{
  switch (id)
  {
   case "tab3":
   model = GetAllUsersInfo();
   viewName = "Administration";
   break;
   }
   return View(viewName);
 }

  private List<AdministrationModel> GetAllUsersInfo()
  {
    List<AdministrationModel> userList = new List<AdministrationModel>();
    foreach (MembershipUser user in Membership.GetAllUsers())
    {
      UserProfile userProfile = UserProfile.GetUserProfile(user.UserName);
      userList.Add(new AdministrationModel { EmailAddress = user.Email,                       IsApproved = user.IsApproved, FirstName = userProfile.FirstName, LastName = userProfile.LastName });
    }

    return userList;
  }

This is my View 这是我的观点

@model List<AdminContainerModel>
@using (Html.BeginForm("Administration", "Account"))
{
  <fieldset>
    <div>
      @foreach (AdministrationModel AM in Model)
      {
        <div>
         <div class="colFull">@Html.DisplayFor(modelItem => AM.FirstName)</div>
         <div class="colFull">@Html.DisplayFor(modelItem => AM.LastName)</div>
         <div class="colFull">@Html.DisplayFor(modelItem => AM.EmailAddress)</div>
         <div class="colPartial"><input type="checkbox" checked="@AM.IsApproved"/>            </div>
      <div class="clear"></div>
    </div>
  }
</div>
 <input type="submit" value="Update Account" />
 </fieldset>
}

When the user clicks the Update Account button it goes to the controller 当用户单击“更新帐户”按钮时,它将转到控制器

  [HttpPost]
  public ActionResult Administration(List<AdministrationModel> model)
  {
     return View();
  }

inside this method, model is always null. 在此方法中,模型始终为null。 however the View that renders everything is perfect and shows what I want it to show. 然而,呈现一切的视图是完美的,并展示了我想要展示的内容。 What am I doing wrong? 我究竟做错了什么?

When using collections, in order to correctly process them so they are model-bound on post without any additional leg work, you need to make sure they are indexed correctly, you can do this by using a for loop, something like: 使用集合时,为了正确处理它们以便它们在帖子上进行模型绑定而不需要任何额外的工作,您需要确保它们被正确编入索引,您可以通过使用for循环来完成此操作,例如:

@for (int i = 0; i < Model.Count; i++)
{
    @Html.HiddenFor(m => m[i].FirstName)
    @Html.HiddenFor(m => m[i].LastName)
    @Html.HiddenFor(m => m[i].EmailAddress)
    <div>
        <div class="colFull">@Html.DisplayFor(m => m[i].FirstName)</div>
        <div class="colFull">@Html.DisplayFor(m => m[i].LastName)</div>
        <div class="colFull">@Html.DisplayFor(m => m[i].EmailAddress)</div>
        <div class="colPartial">@Html.CheckBoxFor(m => m[i].IsApproved)</div>
        <div class="clear"></div>
    </div>
}

That should model bind without any other code :) 这应该模型绑定没有任何其他代码:)

Edit: Sorry I forgot, displayFors by default don't put the correct properties on for model binding, added hiddenFors for the other fields that don't have an editorFor 编辑:对不起我忘了,displayFors默认情况下没有为模型绑定添加正确的属性,为没有editorFor的其他字段添加了hiddenFors

Edit2: Based on your other question in the comment, if it was public facing and you didn't want them to change any of the hidden for values using the dev tools, try the following: 编辑2:根据评论中的其他问题,如果它是面向公众的,并且您不希望他们使用开发工具更改任何隐藏的值,请尝试以下操作:

Ok so you don't want them to change the hiddenFors, that's fine, but you will need some sort of ID so you know which client is which when the data is posted, I suggest that instead of having these in the above code: 好的,所以你不希望他们改变hiddenFors,这很好,但是你需要某种ID,这样你就知道哪个客户端在发布数据的时候,我建议不要在上面的代码中使用这些:

@Html.HiddenFor(m => m[i].FirstName)
@Html.HiddenFor(m => m[i].LastName)
@Html.HiddenFor(m => m[i].EmailAddress)

Replace them with: 替换为:

@Html.HiddenFor(m => m[i].ClientId)

That way you're not posting back the firstname, lastname or email address, just a reference to the actual client that is ticked, unticked. 这样你就不会回复名字,姓氏或电子邮件地址,只是对未勾选的实际客户的引用。

To answer your other question in the comment about keeping track of the original values, in your controller method you can just go and get the original values from the database, then here's how you can detect which ones are different, something like: 要在关于跟踪原始值的注释中回答您的其他问题,您可以在控制器方法中从数据库中获取原始值,然后在此处检测哪些是不同的,例如:

[HttpPost]
public ActionResult Administration(List<AdministrationModel> model)
{
    var originalMatches = GetAllUsersInfo();

    var differences = (from o in originalMatches
                      join c in model on o.ClientId equals c.ClientId
                      where c.IsApproved != o.IsApproved).ToList()

    return View();
}

Your @model directive is incorrect, it should be the fully qualified type name. 您的@model指令不正确,它应该是完全限定的类型名称。

In this case: 在这种情况下:

 @model TheNamespace.AdministrationModel

After your updated question. 更新后的问题。

Try using: 尝试使用:

@Html.EditorFor(Model)

This will call a specialized Editor Template for your list. 这将为您的列表调用专用的编辑器模板

http://blogs.msdn.com/b/nunos/archive/2010/02/08/quick-tips-about-asp-net-mvc-editor-templates.aspx http://blogs.msdn.com/b/nunos/archive/2010/02/08/quick-tips-about-asp-net-mvc-editor-templates.aspx

如果要在提交时返回包含模型的列表项,则需要使用for循环,而不是foreach

Matty's answer will work. 马蒂的回答将起作用。

If you want to avoid having to specify indexes (which wouldn't work if you had an ICollection) you can define a child template as Xander has explained. 如果您想避免必须指定索引(如果您有ICollection则无法工作),您可以像Xander所解释的那样定义子模板。

The benefit is you still get all your strong typed intellisense in the AdminContainerModel View and MVC hooks the items back in to your List on post back for you out of the box. 好处是你仍然可以在AdminContainerModel视图中获得所有强类型的智能感知,并且MVC将这些项目挂回到你的列表中,然后开箱即用。

Here's an example: 这是一个例子:

Main Editor template (as Xander said): 主编辑模板(正如Xander所说):

    @model IEnumerable<AdminContainerModel>
    @using (Html.BeginForm("Administration", "Account"))
    {
      <fieldset>
        <div>
          @Html.EditorForModel()
        </div?
      </fieldset>
    }

AdminContainerModel Editor template(This is called for each item in your List because you've called @Html.EditorForModel: AdminContainerModel编辑器模板(为列表中的每个项调用此模板,因为您调用了@ Html.EditorForModel:

@model AdminContainerModel
<div>
    <div class="colFull">@Html.DisplayFor(modelItem => AM.FirstName)</div>
    <div class="colFull">@Html.DisplayFor(modelItem => AM.LastName)</div>
    <div class="colFull">@Html.DisplayFor(modelItem => AM.EmailAddress)</div>
    <div class="colPartial"><input type="checkbox" checked="@AM.IsApproved"/>            
</div>
<div class="clear"></div>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM