Giả sử tôi có một mô hình sản phẩm, mô hình sản phẩm có một thuộc tính ProductSubType (trừu tượng) và chúng tôi có hai cách triển khai cụ thể là áo sơ mi và quần.Mô hình MVC 3 Ràng buộc một loại phụ (Lớp trừu tượng hoặc giao diện)
Dưới đây là nguồn:
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; }
}
Trong giao diện người dùng của tôi, người dùng có một thả xuống, họ có thể chọn các loại sản phẩm và các yếu tố đầu vào sẽ được hiển thị theo loại sản phẩm thích hợp. Tôi có tất cả điều này được tìm ra (bằng cách sử dụng ajax nhận được trên thay đổi thả xuống, trả về một phần/trình soạn thảo mẫu và tái thiết lập xác nhận jquery cho phù hợp).
Tiếp theo, tôi đã tạo một trình kết nối mô hình tùy chỉnh cho 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;
}
}
Điều này ràng buộc các giá trị chính xác và hoạt động cho hầu hết các phần, ngoại trừ tôi mất xác thực phía máy chủ. Vì vậy, trên một linh cảm rằng tôi đang làm này không chính xác tôi đã làm một số tìm kiếm hơn và đã xem qua câu trả lời này bởi Darin Dimitrov:
ASP.NET MVC 2 - Binding To Abstract Model
Vì vậy, tôi chuyển sang mô hình chất kết dính để chỉ ghi đè CreateModel, nhưng bây giờ nó không ràng buộc các giá trị.
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;
}
Đẩy mạnh dù MVC 3 src, nó có vẻ như trong BindProperties, các GetFilteredModelProperties trả về một kết quả có sản phẩm nào, và tôi nghĩ là vì mô hình BindingContext được thiết lập để ProductTypeBase mà không có bất cứ tài sản.
Có ai có thể phát hiện ra những gì tôi đang làm sai? Điều này dường như không phải là khó khăn như vậy. Tôi chắc chắn tôi thiếu một cái gì đó đơn giản ... Tôi có một thay thế trong tâm trí thay vì có một tài sản SubProduct trong mô hình sản phẩm để chỉ có các thuộc tính riêng biệt cho áo sơ mi và quần. Đây chỉ là các mô hình Xem/Biểu mẫu nên tôi nghĩ điều đó sẽ hiệu quả, nhưng muốn có cách tiếp cận hiện tại đang hoạt động nếu có bất cứ điều gì để hiểu điều gì đang xảy ra ...
Cảm ơn sự giúp đỡ của bạn!
Cập nhật:
Tôi không làm cho nó rõ ràng, nhưng mô hình tùy chỉnh chất kết dính Tôi nói thêm, được thừa hưởng từ DefaultModelBinder
trả lời
Thiết ModelMetadata và Model là phần còn thiếu. Cảm ơn Manas!
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);
}
Hoàn hảo, đặt ModelMetaData và Mô hình tạo ra là phần bị thiếu, cảm ơn! –
Tôi đã có một vấn đề rất giống với một loại thừa hưởng và có nguồn gốc và mã mô hình ở trên đã làm các trick. Chúc mừng! –
Cảm ơn! Tôi dành gần ba ngày để thử những thứ khác nhau để cuối cùng sử dụng giải pháp này, mặc dù vấn đề của tôi có phần khác biệt. –