我正在试验这个问题,我想出了一个解决方案。我创建了一个名为 InterfaceModelBinder 的类:
public class InterfaceModelBinder : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ModelBindingContext context = new ModelBindingContext(bindingContext);
var item = Activator.CreateInstance(
Type.GetType(controllerContext.RequestContext.HttpContext.Request.Form["AssemblyQualifiedName"]));
Func<object> modelAccessor = () => item;
context.ModelMetadata = new ModelMetadata(new DataAnnotationsModelMetadataProvider(),
bindingContext.ModelMetadata.ContainerType, modelAccessor, item.GetType(), bindingContext.ModelName);
return base.BindModel(controllerContext, context);
}
}
我在我的 Application_Start 中这样注册:
ModelBinders.Binders.Add(typeof(IFormSubmission), new InterfaceModelBinder.Models.InterfaceModelBinder());
接口和具体实现如下所示:
public interface IFormSubmission
{
}
public class ContactForm : IFormSubmission
{
public string Name
{
get;
set;
}
public string Email
{
get;
set;
}
public string Comments
{
get;
set;
}
}
整个方法的唯一缺点(您可能已经收集到)是我需要从某个地方获取 AssemblyQualifiedName ,在此示例中,它被存储为客户端的隐藏字段,如下所示:
<%=Html.HiddenFor(m => m.GetType().AssemblyQualifiedName) %>
我不确定将类型名称暴露给客户端的缺点是否值得失去这种方法的好处。像这样的 Action 可以处理我所有的表单提交:
[HttpPost]
public ActionResult Process(IFormSubmission form)
{
if (ModelState.IsValid)
{
FormManager manager = new FormManager();
manager.Process(form);
}
//do whatever you want
}
对这种方法有什么想法吗?