說我有一個產品型號,產品型號有ProductSubType(抽象)的性質,我們有兩個具體的實現上衣和褲子。MVC 3模型綁定一個子類型(抽象類或接口)
這裏是源:
public class Product
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
[Required]
public decimal? Price { get; set; }
[Required]
public int? ProductType { get; set; }
public ProductTypeBase SubProduct { get; set; }
}
public abstract class ProductTypeBase { }
public class Shirt : ProductTypeBase
{
[Required]
public string Color { get; set; }
public bool HasSleeves { get; set; }
}
public class Pants : ProductTypeBase
{
[Required]
public string Color { get; set; }
[Required]
public string Size { get; set; }
}
以我UI,用戶有一個下拉菜單中,他們可以選擇產品類型和輸入元件根據合適的產品類型顯示。我已經想通了所有這些(使用ajax get dropdown change,返回一個局部/編輯器模板並相應地重新設置jquery驗證)。
接下來,我爲ProductTypeBase創建了一個自定義模型聯編程序。
public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
{
ProductTypeBase subType = null;
var productType = (int)bindingContext.ValueProvider.GetValue("ProductType").ConvertTo(typeof(int));
if (productType == 1)
{
var shirt = new Shirt();
shirt.Color = (string)bindingContext.ValueProvider.GetValue("SubProduct.Color").ConvertTo(typeof(string));
shirt.HasSleeves = (bool)bindingContext.ValueProvider.GetValue("SubProduct.HasSleeves").ConvertTo(typeof(bool));
subType = shirt;
}
else if (productType == 2)
{
var pants = new Pants();
pants.Size = (string)bindingContext.ValueProvider.GetValue("SubProduct.Size").ConvertTo(typeof(string));
pants.Color = (string)bindingContext.ValueProvider.GetValue("SubProduct.Color").ConvertTo(typeof(string));
subType = pants;
}
return subType;
}
}
這正確地綁定了這些值,並且大部分工作,除了我失去了服務器端驗證。因此,在一種預感,我做這個錯誤我做了一些更多的搜索和達林季米特洛夫碰到這個答案出來:
ASP.NET MVC 2 - Binding To Abstract Model
所以我交換模型綁定只覆蓋CreateModel,但現在它不綁定值。
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
ProductTypeBase subType = null;
var productType = (int)bindingContext.ValueProvider.GetValue("ProductType").ConvertTo(typeof(int));
if (productType == 1)
{
subType = new Shirt();
}
else if (productType == 2)
{
subType = new Pants();
}
return subType;
}
步進雖然MVC 3 SRC,好像在BindProperties的GetFilteredModelProperties返回一個空的結果,我想是因爲的BindingContext模型設置爲ProductTypeBase不具有任何屬性。
任何人都可以發現我做錯了什麼嗎?這似乎不應該是這樣的困難。我相信我缺少一些簡單的東西......我有另一種選擇,而不是在產品模型中有一個SubProduct屬性來爲襯衫和褲子分別設置屬性。這些都只是查看/錶款,所以我認爲這工作,但想獲得當前的方法工作,如果任何瞭解是怎麼回事...
感謝您的幫助!
更新:
我沒有說清楚,但我添加的自定義模型綁定,從DefaultModelBinder
回答
設置ModelMetadata和型號是缺少的部分繼承。感謝瑪納斯!
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
if (modelType.Equals(typeof(ProductTypeBase))) {
Type instantiationType = null;
var productType = (int)bindingContext.ValueProvider.GetValue("ProductType").ConvertTo(typeof(int));
if (productType == 1) {
instantiationType = typeof(Shirt);
}
else if (productType == 2) {
instantiationType = typeof(Pants);
}
var obj = Activator.CreateInstance(instantiationType);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, instantiationType);
bindingContext.ModelMetadata.Model = obj;
return obj;
}
return base.CreateModel(controllerContext, bindingContext, modelType);
}
完美的是,將ModelMetaData和Model設置爲創建是缺失的部分,謝謝! – 2012-02-24 14:50:27
我有一個非常類似的問題與繼承和派生類型和上述模型聯編程序代碼做了伎倆。乾杯! – 2012-03-27 04:54:47
謝謝!我花了差不多三天的時間嘗試不同的方式來最終使用這個解決方案,儘管我的問題有所不同。 – 2013-02-05 11:19:37