0

我正在使用 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;

当我在 View 上的 Json 中获得质押模型时,我得到以下 json:

{"name":"Moses","Assets":[{"CityId":1,"commetns":null}, {"LicenseNumber":"7654321","commetns":null}]};

如果我试图在 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 开发人员工具中单击请求的红色错误)“无法创建抽象类”

但是如果资产清单是空的——我的承诺是正确的

请帮忙

谢谢

4

2 回答 2

0

感谢http://maciejlis.com/asp-mvc-3-model-binder-with-abstract-class-support/ 我得到了解决问题的方法:

我添加了 customBinder(完全从 maciejlis 博客复制)这个自定义绑定器根据类型属性映射资产对象(必须与资产类名称完全相同)

    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);
            }
        }
    }

现在剩下的就是为每个资产对象添加“类型”属性:

            $(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

于 2013-01-13T16:46:26.750 回答
0

在您的 Ajax 调用中,质押是从什么生成的?如果它是一个表单,您需要确保每个抽象资产的所有属性都以某种方式包含在表单中。如果您不希望这些成为用户可以编辑的输入字段,请将输入字段上的类型设置为隐藏。

希望有帮助!

于 2013-01-09T11:58:13.143 回答