首先,對於大帖子(我試着先做一些研究)以及對同一問題的技術組合(ASP.NET MVC 3,Ninject和MvcContrib)。ASP.NET MVC 3:帶繼承性/多態性的DefaultModelBinder
我正在開發一個ASP.NET MVC 3項目來處理一些客戶端命令。
總之:我有一些繼承自對象的抽象類和抽象類Order
,我需要在向我的控制器發出POST請求時解析它們。我如何解決正確的類型?我是否需要重寫DefaultModelBinder
類,或者有其他方法可以做到這一點?有人可以提供我一些代碼或其他鏈接關於如何做到這一點?任何幫助將是偉大的! 如果帖子令人困惑,我可以做任何更改以清楚說明!
所以,我對我的訂單需要處理以下繼承樹:
public abstract partial class Order {
public Int32 OrderTypeId {get; set; }
/* rest of the implementation ommited */
}
public class OrderBottling : Order { /* implementation ommited */ }
public class OrderFinishing : Order { /* implementation ommited */ }
這班都是由實體框架生成的,所以我不會改變他們,因爲我將需要更新模型(我知道我可以擴展它們)。此外,還會有更多訂單,但全部來自Order
。
我有一個通用視圖(Create.aspx
)爲了創建一個訂單,並且這個視圖爲每個繼承的訂單(在這種情況下爲OrderBottling
和OrderFinishing
)調用強類型的局部視圖。我爲OrderController
類定義了一個用於GET請求的Create()
方法和用於POST請求的其他方法。第二是這樣的:
public class OrderController : Controller
{
/* rest of the implementation ommited */
[HttpPost]
public ActionResult Create(Order order) { /* implementation ommited */ }
}
現在的問題:當我接收與從形式的數據POST請求,MVC的默認粘合劑嘗試實例化Order
對象,這是因爲該方法的類型確定就是它。但是因爲Order
是抽象的,所以它不能實例化,這是應該做的。
問題:怎樣才能發現哪個具體的Order
類型是由視圖發送的?
我已經在這裏搜索了堆棧溢出並搜索了很多關於這個(我正在處理這個問題大約3天了!),並找到了一些方法來解決一些類似的問題,但我找不到像我真正的問題。爲解決此有兩個選項:
- 覆蓋ASP.NET MVC
DefaultModelBinder
,並使用缸內直噴發現哪個類型是Order
; - 爲每個訂單創建一個方法(不漂亮,並且會有問題維護)。
我還沒有嘗試第二種方法,因爲我不認爲這是解決問題的正確方法。對於第一個選項,我嘗試過Ninject來解析訂單的類型並實例化它。我Ninject模塊是這樣的:
private class OrdersService : NinjectModule
{
public override void Load()
{
Bind<Order>().To<OrderBottling>();
Bind<Order>().To<OrderFinishing>();
}
}
我試圖讓各類throught Ninject的Get<>()
方法之一,但它告訴我,該是解決其種類較多,其中一個方法。所以,我明白這個模塊並沒有很好的實現。我也試圖對這兩種類型執行:Bind<Order>().To<OrderBottling>().WithPropertyInject("OrderTypeId", 2);
,但它有同樣的問題...什麼纔是實現這個模塊的正確方法?
我也嘗試使用MvcContrib模型綁定。我已經做到了這一點:
[DerivedTypeBinderAware(typeof(OrderBottling))]
[DerivedTypeBinderAware(typeof(OrderFinishing))]
public abstract partial class Order { }
和Global.asax.cs
我已經做到了這一點:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
ModelBinders.Binders.Add(typeof(Order), new DerivedTypeModelBinder());
}
但是,這將引發異常:system.missingMethodException而:無法創建抽象類。所以,我認爲活頁夾不是或不能解析爲正確的類型。
許多許多在此先感謝!
編輯:首先,感謝Martin和Jason的回答,併爲延誤感到抱歉!我嘗試了兩種方法,並且都奏效了!我將馬丁的答案標記爲正確,因爲它更靈活,並滿足我項目的一些需求。具體地,對於每個請求的ID被存儲在數據庫中,如果我只在一個地方(數據庫或在類)更改ID把它們的類可以打破軟件。馬丁的方法在這一點上非常靈活。
@馬丁:我的代碼我改了行
var concreteType = Assembly.GetExecutingAssembly().GetType(concreteTypeValue.AttemptedValue);
到
var concreteType = Assembly.GetAssembly(typeof(Order)).GetType(concreteTypeValue.AttemptedValue);
,因爲我所在的班的另一個項目(等,在不同的組件)。我分享這個,因爲它看起來像比只獲取不能解析外部程序集類型的執行程序集更靈活。在我的情況下,所有的訂單類都在同一個程序集上。這不是最好,也不是一個神奇的公式,但我覺得有趣的是,分享這個;)
完整的堆棧跟蹤總是可以更容易地診斷問題。 – 2011-03-28 14:20:50
@jmpcm - 只要確定,如果從'Order'中刪除'abstract'修飾符,它是否工作? – 2011-03-28 14:32:33
@Sergi:不,它也不起作用。我之前創建模型的時候,我沒有把Order作爲抽象的,結果是一樣的,但有一個不同的錯誤(不記得它是什麼)。 – jmpcm 2011-03-28 14:35:27