什么是适当的方法从MVC4中的视图将2个不同的模型传递给控制器

时间:2014-05-26 17:53:14

标签: c# asp.net-mvc asp.net-mvc-3 asp.net-mvc-4

我正在使用SimpleCmbership的MVC4。 MVC设置了我的UserProfile表,并且我修改了注册视图以适应我的布局。一切都很顺利,直到我确定我想要从我的用户那里包含一些最适合其他现有模型的附加信息。

通常,我将多个模型从View传递给Controller的方法是使用元组。从历史上看,这对我来说非常有用,而且直到现在我还没有遇到任何实际问题。

我的注册表格类似于:

@model Tuple<MyNamespace.Models.RegisterModel,MyNamespace.Models.MembershipDetail>

@using (Html.BeginForm(new { ReturnUrl = ViewBag.ReturnUrl })) {
@Html.AntiForgeryToken()     
    <table style="border-collapse: collapse; border-spacing:0px; border-width:0px; margin: 0px; width:100px; padding: 0 0 0 0px; background-color:#2e2e2e;">
        <tr>
           <td>
              Profile Name
           </td>
           <td>
              @Html.TextBoxFor(m => m.Item2.ProfileName)
           </td>
        </tr> 
        <tr>
           <td>
              @Html.LabelFor(m => m.Item1.UserName)
           </td>
           <td>
              @Html.TextBoxFor(m => m.Item1.UserName)
           </td>
        </tr>
        <tr>
           <td>
              @Html.LabelFor(m => m.Item1.Password)
           </td>
           <td>
              @Html.PasswordFor(m => m.Item1.Password)
           </td>
        </tr>
        <tr>
           <td>
              @Html.LabelFor(m => m.Item1.ConfirmPassword)
           </td>
           <td>
              @Html.PasswordFor(m => m.Item1.ConfirmPassword)
           </td>
        </tr>                               
        <tr>
           <td>
              <button type="submit" id="btnSubmitForm" value="Register">Register</button>
           </td>
        </tr>
     </table>
     @Html.Partial("_ValidationSummary",ViewData.ModelState)                             
   }    

我的控制器的注册方法与此类似:

    [HttpPost]
    [AllowAnonymous]
    [ValidateAntiForgeryToken]
    public ActionResult Register(RegisterModel model, MembershipDetail member)
    {
        if (ModelState.IsValid)
        {
            try
             {
                // Do something with the data
             }
            catch(MembershipCreateUserException e)
            {
               ModelState.AddModelError("",ErrorCodeToString(e.StatusCode));
            }
        }
        return View(model);
    }

每当我在单击Submit按钮后调试此代码时,我会注意到返回控制器的两个Models都是空的。包含的字段是null,0或Empty Strings,我无法弄清楚原因。

要添加这个谜团,如果我从视图顶部删除元组并将其重新分配为单个模型:

@model MyNamespace.Models.RegisterModel

将代码中的元组引用(例如m.Item1.Property,m.Item2.Property)替换为1 Model推断引用(m.Property等);然后从TextBox助手传入的数据被适当地分配给模型,并在调试代码时填充模型。

现在,我知道我可以简单地在UserProfile表中添加一些其他字段,并在我的模型中使用它们来完全缓解元组,但后来我复制了我的模式中的数据,这不是一个理想的解决方案。请记住,尽管此处提供的示例代码仅包含第二个模型的1个元素,但它实际上将超过1个。

那么为什么在使用元组时不会填充模型,是否有更合适的方法来解决这个问题?或者我不能在单个表单提交中混合模型数据???

1 个答案:

答案 0 :(得分:4)

首先,使用Tuple作为模型并不是一个好习惯,因为很难阅读代码。您应该为此编写页面自己的视图模型。 对于这个例子,如:

 public class SomeViewModel{
         public RegisterModel RegisterModel { get; set;}
         public MembershipDetail MembershipDetail {get; set;}
 } 

它易于实施,并可以按您的需要工作。

但是,如果您想在视图上使用Tuples作为模型。

你应该得到像

这样的帖子
   public ActionResult Register(Tuple<RegisterModel,MembershipDetail> model)
   {
     .... // do something..
   }

因为表单html的创建方式如下:

  <input name="Item1.ProfileName" />  

你可以看到,它会尝试发送默认模型绑定器不支持的Item1.Profile名称,将其转换为你自己的类..它会期望一个元组或类如下:。

   public class TheClass {
    public RegisterModel Item1 {get; set;}
    public MemberhipDetail Item2 {get; set;}
 }

基本上就像viewmodel