C# MVC4复杂类型模型在post后为空

C# MVC4复杂类型模型在post后为空,c#,asp.net-mvc,asp.net-mvc-4,razor,C#,Asp.net Mvc,Asp.net Mvc 4,Razor,这是我的模型 public class AdministrationModel { public string FirstName { get; set; } public string LastName { get; set; } public string EmailAddress { get; set; } public bool IsApproved { get; set; } } 这是我的控制器 public ActionResult GetTabContent(st

这是我的模型

public class AdministrationModel
{
  public string FirstName { get; set; }
  public string LastName { get; set; }
  public string EmailAddress { get; set; }
  public bool IsApproved { get; set; }
}
这是我的控制器

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;
  }
  [HttpPost]
  public ActionResult Administration(List<AdministrationModel> model)
  {
     return View();
  }
public ActionResult GetTabContent(字符串id)
{
开关(id)
{
案例“表3”:
模型=GetAllUsersInfo();
viewName=“管理”;
打破
}
返回视图(viewName);
}
私有列表GetAllUsersInfo()
{
List userList=新列表();
foreach(Membership.GetAllUsers()中的MembershipUser用户)
{
UserProfile UserProfile=UserProfile.GetUserProfile(user.UserName);
userList.Add(新的管理模型{EmailAddress=user.Email,IsApproved=user.IsApproved,FirstName=userProfile.FirstName,LastName=userProfile.LastName});
}
返回用户列表;
}
这是我的看法

@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>
}
@型号列表
@使用(Html.BeginForm(“管理”、“帐户”))
{
@foreach(模型中的管理模型AM)
{
@DisplayFor(modelItem=>AM.FirstName)
@DisplayFor(modelItem=>AM.LastName)
@DisplayFor(modelItem=>AM.EmailAddress)
}
}
当用户单击更新帐户按钮时,它将转到控制器

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;
  }
  [HttpPost]
  public ActionResult Administration(List<AdministrationModel> model)
  {
     return View();
  }
[HttpPost]
公共行动结果管理(列表模型)
{
返回视图();
}

在这个方法中,模型总是空的。然而,呈现一切的视图是完美的,并且显示了我希望它显示的内容。我做错了什么?

您的
@model
指令不正确,它应该是完全限定的类型名

在这种情况下:

 @model TheNamespace.AdministrationModel

更新后的问题

尝试使用:

@Html.EditorFor(Model)
这将为您的列表调用专门的编辑器模板


使用集合时,为了正确处理它们,使它们在post上绑定到模型,而不需要任何额外的分支工作,您需要确保它们的索引正确,您可以使用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>
}
替换为:

@Html.HiddenFor(m => m[i].ClientId)
这样,您就不会发回名字、姓氏或电子邮件地址,而只是对实际客户的一个引用,即勾选、取消勾选

要回答评论中关于跟踪原始值的另一个问题,在控制器方法中,您只需从数据库中获取原始值,然后以下是如何检测哪些值不同,如:

[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();
}
[HttpPost]
公共行动结果管理(列表模型)
{
var originalMatches=GetAllUsersInfo();
var差异=(从原始匹配中的o开始)
在o.ClientId等于c.ClientId的模型中加入c
其中c.IsApproved!=o.IsApproved
返回视图();
}

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

Matty的答案将起作用

如果您想避免必须指定索引(如果您有ICollection,那么这将不起作用),您可以定义一个子模板,正如Xander所解释的那样

好处是,您仍然可以在AdminContainerModel视图中获得所有强类型的intellisense,并且MVC会将这些项目挂回到您的列表中,以便您即时返回

下面是一个例子:

主编辑器模板(正如Xander所说):

@model IEnumerable
@使用(Html.BeginForm(“管理”、“帐户”))
{
@Html.EditorForModel()

你说的是视图吗?如果是的话,我只是删除了名称空间,将其发布到这里。显示视图显示数据没有问题,它在HTTPPost调用期间模型为null。你想让我用EditorFor替换DisplayFor吗?我试过了,发布后我的模型仍然为null。我确信我遗漏了什么(只是不确定它是什么)您需要一个EditorTemplate视图来映射
AdministrationModel
Html.EditorFor(Model)
将查找此视图。使用此视图后,无需在列表中循环。好的,我是这样做的。但是,这会将模型中的所有内容呈现为可编辑字段。我只想编辑“IsApproved”复选框。选中/取消选中后,我需要根据电子邮件地址查找用户并更新他/她。我希望这是有意义的。您可以在viewmodel的属性上设置表示自己为“不可编辑”的属性-这应该有帮助:这对我没有帮助。在回发事件中-名字、姓氏和电子邮件地址的所有值都为空。我想要一个所有已更改值的集合(复选框从选中变为未选中或未选中变为选中)抱歉,请检查我的编辑,我忘记了displayFors没有将名称属性放在字段上以正确地进行模型绑定(我们更改了模板进行绑定)。在控制器中,您可以在未签入的链接上进行筛选,例如var clients=model.Where(c=>c.IsApproved)。ToList()它工作得很好,但是我有两个问题:1.如果有人更改隐藏字段值(几乎每个浏览器中都有开发工具)然后模型中的值也会发生变化2.lamda表达式只给出所有已检查的列表,我如何跟踪已检查和已在此会话中检查的。1.这是一个面向公众的网站,您不想让人们操纵它吗?2.您可以将您的模型设为复杂类型控制正在创建两个客户端列表,一个是您正在编辑的客户端,另一个是原始客户端。对两个集合重复上述for循环,但只有原始集合的所有隐藏字段。只是想说声谢谢!将foreach替换为修复了绑定。如果他所更改的是foreach,那么这应该是一个注释,因为它可以工作,所以这是一个解决方案好的,问题是你只是在“指出一些东西”——答案应该比这更深刻对不起,我想我是想礼貌一点,在写之前识别出被接受的答案
@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>