我正在使用MVC asp.net 4和jquery。 这是我的问题: 我有以下模型:
public class PledgeModel
{
public string name { get; set; }
public IList<AbstractAsset> Assets { get; set; }
}
如果它的属性是对象列表,则每个属性都继承抽象类:
public abstract class AbstractAsset
{
public string commetns { get; set; }
}
public class RealEstateAsset:AbstractAsset
{
public int CityId { get; set; }
}
public class TransportationAsset : AbstractAsset
{
public string LicenseNumber { get; set; }
}
}
这是我的“获取”操作代码:
//init new Pledge
PledgeModel pledge=new PledgeModel();
pledge.name = "Moses";
pledge.Assets=new List<AbstractAsset>();
RealEstateAsset realEstateAsset = new RealEstateAsset();
TransportationAsset transportationAsset=new TransportationAsset();
realEstateAsset.CityId = 1;
transportationAsset.LicenseNumber = "7654321";
pledge.Assets.Add(realEstateAsset);
pledge.Assets.Add(transportationAsset);
ViewBag.Pledge = pledge;
当我在Json上获得承诺模型时,我正在关注json:
{ “名称”: “摩西”, “资产”:[{ “CityId”:1, “commetns”:空} { “LicenseNumber”: “7654321”, “commetns”:空}]};
如果我试图在ajax回调中发送整个模型及其资产列表:
var ajaxOptions = {
type: 'post',
url: 'Home/TryInsertPledge',
contentType: "application/json, charset=utf-8;",
dataType:'json',
data:JSON.stringify({pledge:pledge}),
success: function(data) {
alert('success');
},
error: function() {
alert('error');
}
};
$.ajax(ajaxOptions);
“发布”行动:
[HttpPost]
public JsonResult TryInsertPledge(PledgeModel pledge)
{
return Json(new {sucess = "success"});
}
由于某些原因我得到了错误(如果你点击chrome开发者工具中的请求的红色错误)'无法创建抽象类'
但是如果资产清单是空的 - 我正确地承诺了我的承诺
请帮忙
由于
答案 0 :(得分:0)
在你的Ajax调用中,生成的承诺是什么?如果是表单,则需要确保每个抽象资产的所有属性都以某种方式包含在表单中。如果您不希望这些是用户可以编辑的输入字段,请将输入字段上的类型设置为隐藏。
希望有所帮助!
答案 1 :(得分:0)
感谢http://maciejlis.com/asp-mvc-3-model-binder-with-abstract-class-support/ 我得到了解决问题的方法:
我添加了customBinder(完全从maciejlis博客复制) 此自定义绑定器根据type属性(必须与资产类名称完全相同)映射资产对象
public class EnhancedDefaultModelBinder : DefaultModelBinder
{
protected override object CreateModel(ControllerContext controllerContext, ModelBindingContext bindingContext, Type modelType)
{
Type type = modelType;
if (modelType.IsGenericType)
{
Type genericTypeDefinition = modelType.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(IDictionary<,>))
{
type = typeof(Dictionary<,>).MakeGenericType(modelType.GetGenericArguments());
}
else if (((genericTypeDefinition == typeof(IEnumerable<>)) || (genericTypeDefinition == typeof(ICollection<>))) || (genericTypeDefinition == typeof(IList<>)))
{
type = typeof(List<>).MakeGenericType(modelType.GetGenericArguments());
}
return Activator.CreateInstance(type);
}
else if (modelType.IsAbstract)
{
string concreteTypeName = bindingContext.ModelName + ".Type";
var concreteTypeResult = bindingContext.ValueProvider.GetValue(concreteTypeName);
if (concreteTypeResult == null)
throw new Exception("Concrete type for abstract class not specified");
type = Assembly.GetExecutingAssembly().GetTypes().SingleOrDefault(t => t.IsSubclassOf(modelType) && t.Name == concreteTypeResult.AttemptedValue);
if (type == null)
throw new Exception(String.Format("Concrete model type {0} not found", concreteTypeResult.AttemptedValue));
var instance = Activator.CreateInstance(type);
bindingContext.ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => instance, type);
return instance;
}
else
{
return Activator.CreateInstance(modelType);
}
}
}
现在剩下的就是为每个资产对象添加“Type”属性:
$(pledge.Assets).each(function () {
this.Type = (typeof this.CityId !== 'undefined') ? 'RealEstateAsset' : 'TransportationAsset';
});
var ajaxOptions = {
type: 'post',
url: 'Home/TryInsertPledge',
dataType: 'json',
contentType: "application/json, charset=utf-8;",
data: JSON.stringify({ pledge: pledge }),
success: function (data) {
alert('success');
},
error: function (xhr) {
alert(xhr.respnseText);
}
};
$.ajax(ajaxOptions);
资产得到了正确的服务器...... 再次感谢maciejlis