【问题标题】:Failing to deserialize json into abstract class in ASP.Net MVC无法将 json 反序列化为 ASP.Net MVC 中的抽象类
【发布时间】:2016-12-18 06:19:29
【问题描述】:

我知道关于这个问题有很多问题和答案,但没有一个对我有帮助。

我有 2 个类继承自一个抽象基类。我试图在我的控制器中编写获取基类作为参数的 POST 方法,但我遇到了异常:

MissingMethodException:无法创建抽象类。

我在这个答案中找到了解决方案:Deserialising Json to derived types in Asp.Net Web API,但没有帮助。

我喜欢这个想法,并一直遵循答案,但仍然遇到同样的异常,我的代码从未被调用过。

为了隔离问题,我启动了新的 ASP.NET 项目(SPA 模板)并检查了我在干净项目上的问题。我的实现:

我的 JsonConverter 实现与答案的一种形式相同:

public abstract class JsonCreationConverter<T> : JsonConverter
{
    /// <summary>
    /// this is very important, otherwise serialization breaks!
    /// </summary>
    public override bool CanWrite => false;

    /// <summary> 
    /// Create an instance of objectType, based properties in the JSON object 
    /// </summary> 
    /// <param name="objectType">type of object expected</param> 
    /// <param name="jObject">contents of JSON object that will be 
    /// deserialized</param> 
    /// <returns></returns> 
    protected abstract T Create(Type objectType, JObject jObject);

    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType,
      object existingValue, JsonSerializer serializer)
    {
        //////////////////////////////////////////
        // This function never get called!!!!!!!!!
        //////////////////////////////////////////

        if (reader.TokenType == JsonToken.Null)
            return null;
        // Load JObject from stream 
        JObject jObject = JObject.Load(reader);

        // Create target object based on JObject 
        T target = Create(objectType, jObject);

        // Populate the object properties 
        serializer.Populate(jObject.CreateReader(), target);

        return target;
    }

    public override void WriteJson(JsonWriter writer, object value,
      JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

我的基类及其实现是:

[JsonConverter(typeof(MyCustomConverter))]
public abstract class BaseClass
{
    private class MyCustomConverter : JsonCreationConverter<BaseClass>
    {
        protected override BaseClass Create(Type objectType,
          Newtonsoft.Json.Linq.JObject jObject)
        {
        //////////////////////////////////////////
        // No matter what I put in here.
        // This function never get called!!!!!!!!!
        //////////////////////////////////////////
            return new Sub1()
            {
                Name = "aaaa",
                Prop1 = 233
            };
        }
    }

    public int Prop1 { get; set; }
}

public class Sub1 : BaseClass
{
    public string Name { get; set; }
}

我的控制器 Post 和 Get 方法是:

    // GET: /Account/GetTest
    [HttpGet]
    public JsonResult GetTest()
    {
        // This function works as expected.
        Sub1 sub1 = new Sub1
        {
            Name = "SomeName",
            Prop1 = 5
        };
        return Json(sub1, JsonRequestBehavior.AllowGet);
    }

    // Post: /Account/PostTest
    [HttpPost]
    public JsonResult PostTest(BaseClass res)
    {
        // I never get to this point.
        return Json(res, JsonRequestBehavior.AllowGet);
    }

而我尝试使用此 API 的 JS 测试代码是:

$.ajax({
    url: '/Account/GetTest',
    method: 'get',
    cache: false,
    success: function(data) {
        // data arrive fine to this point        

        $.ajax({
            url: '/Account/PostTest',
            method: 'post',
            cache: false,
            data: data,
            // I've also tried: data: JSON.stringify(data),
            success: function () {
                // I never get success...
                alert('Success');
            },
            error: function () {
                alert('Error Post');
            }
        });

    },
    error: function() {
        alert('Error Get');
    }
});

我也尝试过使用 ajax 参数,但没有任何运气。

有人知道我做错了什么吗?

【问题讨论】:

  • BaseClass 我认为是抽象的?
  • 这很奇怪,你写的那些没有被调用的方法应该被调用 - 你仍然得到同样的异常吗?
  • 正如您在我的代码中看到的,BaseClass 是抽象的。真奇怪。我想弄清楚这两天了。我确实得到了完全相同的例外......

标签: c# asp.net json asp.net-mvc asp.net-mvc-4


【解决方案1】:

经过多次实验,我发现在基类上使用 JsonConverter 属性只在 ApiController 中有效,在常规 MVC Controller 中无效>。我刚刚创建了新的 ApiController,它就像一个魅力。

另外,当发布 json 时,它应该包含 contentType 信息,所以它应该看起来像:

$.ajax({
        url: '/Account/PostTest',
        method: 'post',
        cache: false,
        //////// NOTE THE NEXT 2 ATTRIBUTES
        data: JSON.stringify(data),
        contentType: 'application/json; charset=utf-8'
        /////////////////
        success: function () {
            // I never get success...
            alert('Success');
        },
        error: function () {
            alert('Error Post');
        }
    });

【讨论】:

    【解决方案2】:
    using (WebClient client = new WebClient())
    {
        response = Newtonsoft.Json.Linq.JObject.Parse(client.DownloadString(fullUrl));
    }
    
    Newtonsoft.Json.Linq.JArray items = response.items;
    
    Newtonsoft.Json.Linq.JArray selectedItems = new JArray();
    
    foreach (dynamic rev in reviews)
    {
        if (rev.propertyWanted == "condition")
        {
             selectedReviews.Add(rev);
        }
        else
        {
            continue;
        }
    }
    
    return selectedReviews;
    

    【讨论】:

    • 这不是我要找的。我总是可以获取json字符串并将其手动解析到基类中,但我正在寻找通用方法...
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-11-18
    • 1970-01-01
    • 1970-01-01
    • 2016-10-08
    • 1970-01-01
    • 2010-10-12
    • 1970-01-01
    相关资源
    最近更新 更多