Asp.net mvc 3 mvc3动态组合页面和表单元素

Asp.net mvc 3 mvc3动态组合页面和表单元素,asp.net-mvc-3,Asp.net Mvc 3,我正在开发一个MVC3应用程序,我有一个页面,一个让用户编辑文档metainfo的视图,一个经典的@Html.BeginForm用法。对于一般文档,用户将看到要填充的标准字段,但通过dropdownlist,他们将能够指定文档的类型:这将通过ajax调用在编辑文档表单上加载新字段。 最后,当用户提交完成的表单时,控制器应读取所有标准字段,以及加载为特定于所选文档类型的所有字段 问题是,我如何处理控制器中的所有这些额外字段? 假设我有Document类和一堆其他类extendinf Documen

我正在开发一个MVC3应用程序,我有一个页面,一个让用户编辑文档metainfo的视图,一个经典的@Html.BeginForm用法。对于一般文档,用户将看到要填充的标准字段,但通过dropdownlist,他们将能够指定文档的类型:这将通过ajax调用在编辑文档表单上加载新字段。 最后,当用户提交完成的表单时,控制器应读取所有标准字段,以及加载为特定于所选文档类型的所有字段

问题是,我如何处理控制器中的所有这些额外字段? 假设我有Document类和一堆其他类extendinf Document,比如Contract:Document、Invoice:Document、Complaint:Document等等,每个类都有特定的属性和加载在表单上的字段,我如何在控制器中编写操作

为了简洁起见,我想使用一些东西,比如我将省略所有的转换、验证等

[HttpPost]
public ActionResult Save(dynamic doc)
{
    int docType = doc.type;
    switch (docType)
    {
        case 1:
            var invoice = new Invoice(doc);
            invoice.amount = Request.Form["amount_field"];
            invoice.code = Request.Form["code_field"];
            //and so forth for every specific property of Invoice
            Repository.Save(invoice);
            break;
        case 2:
            var contract = new Contract(doc);
            contract.fromDate = Request.Form["fromDate_field"];
            contract.toDate = Request.Form["toDate_field"];
            //and so forth for every specific property of Contract
            Repository.Save(contract);
            break;
        ..... // and so forth for any document types

        default:
            break;
    }
}
但对我来说,这似乎是一种非常肮脏的做法。你对如何实现这一目标有更好的想法吗?也许有一种模式,我对这种情况一无所知

更新

我想到了第二个主意。在评论了Rob Kent的答案之后,我想我可以采取另一种方法,只使用一个类文档,其属性如下

public IEnumerable<Field> Tipologie { get; set; } 
但是我应该在视图中创建字段,以便让MVC引擎绑定回模型吗?
考虑到在第一种方法中从文档继承的类可能会在运行时生成,您更喜欢第二种方法吗?

为了在服务器上保持所有的硬类型,您可以使用带有自定义绑定器的抽象基类型。请参见我的答案,了解其工作原理:

其思想是,每次加载一组新字段时,您都将BindingType表单变量更改为处理程序的实例化类型。自定义活页夹负责在提交时创建正确的类型,然后您可以在您的操作中对此进行评估,例如:

if (model is Contract) ...
我不确定您是否能够设置不同的操作,每个操作都有不同的签名,例如:

public ActionResult Save(Contract contract) ...
public ActionResult Save(Invoice invoice) ...
很确定这是行不通的,因为Mvc已经决定了调用哪个方法,或者它会先看看返回的是什么类型,然后再决定


在我的链接示例中,我正在检查重写的基本成员,但如果这不是您的问题,您只需要创建正确的类型。

据我所知,我现在尝试过,mvc不支持在同一控制器上使用相同名称但不同签名的不同操作,除非您指定不同的Http方法。此外,在实际的应用程序中,我不知道从文档派生的类有哪些和多少:所有这些类都将在运行时根据数据库上的值动态创建和编译。是的,这会起作用,因为您只是创建一个属性包。但是,它实际上是否有助于您区分文档的类型?您最终将得到一个松散类型的文档,但由于您在答复中说您不知道自己有什么类型,因此您将不得不接受这一约束。
if (model is Contract) ...
public ActionResult Save(Contract contract) ...
public ActionResult Save(Invoice invoice) ...