1

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

考虑以下模型:

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>

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

<input type="text" id="Form1_PropNameCollision" name="Form1.PropNameCollision" ... />

问题:是否有一种聪明的方法来创建一个在上下文中查找特定类型并绑定+返回的绑定器?我在重写默认绑定器时做了一些涂鸦BindModel,设法将基元与反射绑定,但路径似乎并不理想(考虑到复杂类型、可空值等)。

编辑:我想避免接受FormCollection模型,因为我想束手无策,这意味着我不想意外使用我不应该使用的数据。假设其他人需要使用代码,或者我在 6 个月后回到它,我忘记了需要分离子类的所有内容。

4

2 回答 2

1

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

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

然后你的主视图可以被强类型化到 FormsContainer 并且你的部分视图可以被强类型化到 Form1 和 Form2。

尽管在您的情况下,我只有一个名为 form 的类,因为两个类的属性相同,并且仅具有 2 个此类属性。

于 2013-03-08T14:34:19.547 回答
0

如果我正确理解了您的情况,那么您可能想尝试一个自定义模型绑定器,如该问题的接受答案中所述。总结一下:

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

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

于 2013-03-08T16:44:32.247 回答