[英]ASP.NET MVC 2 - Binding To Abstract Model
如果我有以下強類型視圖:
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<XXX.DomainModel.Core.Locations.Location>" %>
位置是抽象類。
我有以下控制器,它通過POST接受強類型模型:
[HttpPost]
public ActionResult Index(Location model)
我收到一個運行時錯誤,指出“無法創建抽象類
這當然有道理。 但是 - 我不確定這里最好的解決方案是什么。
我有很多具體的類型(大約8個),這是一個只能編輯抽象類屬性的視圖。
我試圖做的是為所有不同的具體類型創建重載,並以通用方法執行我的邏輯。
[HttpPost]
public ActionResult Index(City model)
{
UpdateLocationModel(model);
return View(model);
}
[HttpPost]
public ActionResult Index(State model)
{
UpdateLocationModel(model);
return View(model);
}
等等
然后:
[NonAction]
private void UpdateLocationModel (Location model)
{
// ..snip - update model
}
但這也不起作用 ,MVC抱怨動作方法含糊不清(也很有意義)。
我們做什么? 我們可以簡單地綁定到抽象模型嗎?
如何為這個抽象類編寫自定義模型綁定器:
public class CustomBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
// TODO: based on some request parameter choose the proper child type
// to instantiate here
return new Child();
}
}
只有當您有一個基於某些用戶操作動態插入輸入元素的表單時,這才有意義。 在這種情況下,您需要傳遞一些額外的參數來指示您需要哪個具體類。 否則我會堅持使用具體的視圖模型作為動作參數。
您還可以構建適用於所有抽象模型的通用ModelBinder。 我的解決方案要求您在視圖中添加一個名為“ ModelTypeName ”的隱藏字段,其值設置為您想要的具體類型的名稱。 但是,應該可以使這個更聰明,並通過將類型屬性與視圖中的字段匹配來選擇具體類型。
在Application_Start()中的 Global.asax.cs文件中:
ModelBinders.Binders.DefaultBinder = new CustomModelBinder();
CustomModelBinder:
public class CustomModelBinder2 : DefaultModelBinder
{
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
var modelType = bindingContext.ModelType;
if (modelType.IsAbstract)
{
var modelTypeValue = controllerContext.Controller.ValueProvider.GetValue("ModelTypeName");
if (modelTypeValue == null)
throw new Exception("View does not contain ModelTypeName");
var modelTypeName = modelTypeValue.AttemptedValue;
var type = modelType.Assembly.GetTypes().SingleOrDefault(x => x.IsSubclassOf(modelType) && x.Name == modelTypeName);
if (type != null)
{
var instance= bindingContext.Model ?? base.CreateModel(controllerContext, bindingContext, type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => instance, type);
}
}
return base.BindModel(controllerContext, bindingContext);
}
}
只是把它扔出去 - 我對別人可能回答的問題非常感興趣,但這就是我在遇到類似情況時最終做的事情;
基本上,我沒有使用模型類作為Action方法中的參數,而是傳入FormCollection
並測試一些已知的鑒別器來確定要創建/編輯的類型,然后從那里使用TryUpdateModel
。
似乎可能有更好的方式,但我從來沒有想過要更多。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.