我正在开发一个MVC3应用程序,我有一个页面(好吧,一个视图),让用户编辑文档的元信息(经典的@Html.BeginForm
用法)。对于一般文档,用户将看到要填充的标准字段,但通过下拉列表,他们将能够指定文档的类型:通过ajax调用,将在edit-document-form上加载新字段。
当用户提交完成的表格时,控制器应该读取所有标准字段,以及加载的所有字段,这些字段特定于所选文档的类型。
问题是,如何在控制器中处理所有这些额外的字段?
假设我有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的回答进行评论之后,我认为我可以采用不同的方法,只有一个类Document
具有类似
public IEnumerable<Field> Tipologie { get; set; }
,其中
public class Field
{
public int IdField { get; set; }
public String Label { get; set; }
public String Value { get; set; }
public FieldType ValueType { get; set; }
public List<String> PossibleValues { get; set; } // needed for ENUMERATION type
}
public enum FieldType
{
STRING, INT, DECIMAL, DATE, ENUMERATION
}
这是一种更好的方法吗?在这种情况下,我可以只有一个像
这样的动作方法[HttpPost]
public ActionResult Save(Document doc)
但是我应该在视图中创建字段以使MVC引擎对模型进行绑定?
鉴于在第一种方法中继承自Document
的类可能会在运行时生成,您是否更喜欢第二种方法?
答案 0 :(得分:0)
要在服务器上保留所有硬类型,您可以使用带有自定义绑定器的抽象基类型。请在此处查看我的回答,了解其工作原理:MVC generic ViewModel
这个想法是每次加载一组新字段时,都会将BindingType表单变量更改为处理程序的实例化类型。自定义绑定器负责在提交时创建正确的类型,然后您可以在操作中评估该类型,例如:
if (model is Contract) ...
我不确定您是否能够使用不同的签名设置不同的操作,例如:
public ActionResult Save(Contract contract) ...
public ActionResult Save(Invoice invoice) ...
非常肯定这不起作用,因为Mvc已经决定调用哪种方法,或者它可能首先会看到它返回的类型然后决定。
在我的链接示例中,我正在检查被覆盖的基本成员,但如果这对您来说不是问题,则只需要创建正确的类型。