仅绑定MVC Action中的模型的子集

时间:2013-03-08 14:26:45

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

我希望在一个页面上显示多个表单,在精美的选项卡上显示每个表单。我以为我会创建一个容器模型来保存工作实际发生的模型。然后我会为控制器中的每个表单(/ tab)创建处理程序,接受特定模型作为我想要使用的参数。

考虑以下模型:

public class FormCollection
{
    public FormsContainer()
    {
        Form1 = new Form1();
        Form2 = new Form2();
    }
    public Form1 Form1 { get; set; }
    public Form2 Form2 { get; set; }
}

public class Form1
{
    public string PropNameCollision { get; set; }

    public DateTime? Form1Date { get; set; }
}

public class Form2
{
    public string PropNameCollision { get; set; }

    public DateTime? Form2Date { get; set; }
}

FormController控制器中:

public ActionResult Form1Handler(Form1 model)
{
    return Content("Doing Form1");
}
public ActionResult Form2Handler(Form2 model)
{
    return Content("Doing Form2");
}

观点:

@model MvcApp.Models.FormCollection
<section id="tab1">
@using (Html.BeingForm("Form1Handler", "Form"))
{
    @Html.TextboxFor(m => m.Form1.PropNameCollision)
    @Html.TextboxFor(m => m.Form1.Form1Date)
    <input type="submit"/>
}
</section>
<section id="tab2">
@using (Html.BeingForm("Form2Handler", "Form"))
{
    @Html.TextboxFor(m => m.Form2.PropNameCollision)
    @Html.TextboxFor(m => m.Form2.Form2Date)
    <input type="submit"/>
}
</section>

当我提交任何一个表单时,默认的模型绑定器无法匹配模型和上下文中的内容,例如绑定Form1的{​​{1}}它会期望PropNameCollision的值,而是PropNameCollision到达,因为这是帮助程序生成的原始HTML标记:

Form1.PropNameCollision

问题: 有没有一种聪明的方法可以创建一个在上下文中查找特定类型的绑定器,并且仅绑定+返回?我已经涂抹了一下,覆盖了默认的绑定器<input type="text" id="Form1_PropNameCollision" name="Form1.PropNameCollision" ... /> ,设法用反射来绑定基元,但路径看起来并不好(考虑到复杂类型,无效等)。

修改:我希望避免接受BindModel模型,因为我想保持双手并列,这意味着我不想意外处理数据我不是应该合作。假设其他人需要使用代码,或者我将在6个月后回到它并且我忘记了需要分离子类的一切。

2 个答案:

答案 0 :(得分:1)

将表单放在部分视图中,然后将它们绑定到您的属性,如此

@Html.Partial("PartialViewForm1", model.Form1)
@Html.Partial("PartialViewForm2", model.Form2)

然后您的主视图可以强类型化为FormsContainer,您的局部视图可以强制键入Form1和Form2。

虽然在你的情况下,我只有一个名为form的类,因为两个类的属性相同,只有2​​个属于这种类型的属性。

答案 1 :(得分:0)

如果我理解您的情况,那么您可能需要尝试自定义模型绑定器,如this question的接受答案中所述。总结一下:

  • 从基类继承不同的模型
  • 为基类提供一个方法,该方法返回一个字符串,用于标识特定实例属于
  • 的类
  • 为基类设置自定义模型绑定器,该类在类的传入实例上调用标识方法,并使用结果确定它实际上是哪个派生类,并返回其实例,并绑定值适当。
  • (如有必要)为各种派生类提供EditorTemplates,并使用@Html.EditorFor显示与各种类实例相关的表单部分。

根据您的控制器逻辑,您可能仍然需要将它们作为基类实例接收,并且要么做一些逻辑来计算将它们转换为什么(不是很漂亮,但它可以工作)或者给基类提供相关的方法这样派生类可以提供自己的实现并利用一点点多态性(更优雅的方法,但有时更棘手)。