无法通过jquery ajax发送带有抽象列表属性的模型

时间:2013-01-09 11:33:25

标签: asp.net asp.net-mvc

我正在使用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开发者工具中的请求的红色错误)'无法创建抽象类'

但是如果资产清单是空的 - 我正确地承诺了我的承诺

请帮忙

由于

2 个答案:

答案 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