JSonConverter没有在C#WebAPI中为我的模型的属性触发

时间:2016-07-24 14:33:08

标签: c# json asp.net-web-api

我的WebAPI应用程序中有一个模型,用.NET 4.0编写,具有System.Net.Mime.ContentType类型的属性,如下所示:

[Serializable]
public class FileData
{
    private ContentType contentType;
    private long size;
    private string name;

    public ContentType ContentType
    {
        get { return  contentType; }
        set { contentType = value; } 
    }

    ...

    /* same getter/setter logic for the other fields  */
}

模型位于与我的Web项目不同的程序集中。

因此,客户端向我发送了一条JSON消息,我需要将其转换为此类:

{
    "size": 12345,
    "contentType": "image/png",
    "name": "avatar.png"
}

为了告诉Json.NET如何转换ContentType我已经注册了我为此目的编写的自定义JsonConverter

JsonFormatter.SerializerSettings.Converters.Add(new ContentTypeJsonConverter());

在上面的代码中,我指的是WebApi应用程序的全局JsonFormatter对象。

因此,当客户端向我发送JSON时,我希望控制器正确解析消息。

不幸的是,它失败并出现错误:

  

"无法从System.String转换或转换为System.Net.Mime.ContentType。"

我知道我可以通过将以下代码添加到我的FileData类来解决这个问题:

public class FileData
{
    ...

    [JsonConverter(typeof(ContentTypeJsonConverter))]
    public ContentType ContentType { /* Getter and Setter */ }
}

但问题是我不能在FileData类型所在的程序集中为JSON.NET引入依赖项。

有没有办法在不改变contentType类的情况下触发FileData成员的正确反序列化?

除了上述内容,我还尝试了Brian Rogers建议的内容:

JsonFormatter.SerializerSettings.ContractResolver = new CustomResolver();

实施以下CustomResolver

class CustomResolver : DefaultContractResolver
{
    protected override JsonContract CreateContract(Type objectType)
    {
        var contract = base.CreateContract(objectType);
        if (objectType == typeof(ContentType))
        {
            contract.Converter = new ContentTypeJsonConverter();
        }
        return contract;
    }
}

结果仍然相同。

1 个答案:

答案 0 :(得分:1)

以下适用于我(Web API 2)。

型号:

<script>

  (function () {
    var QUEUE = MathJax.Hub.queue;  
    var math = null, box = null;    
    var HIDEBOX = function () {box.style.visibility = "hidden"}
    var SHOWBOX = function () {box.style.visibility = "visible"}

    QUEUE.Push(function () {
      math = MathJax.Hub.getAllJax("MathOutput")[0];
      box = document.getElementById("box");
      SHOWBOX(); // box is initially hidden so the braces don't show
    });

    window.UpdateMath = function (TeX) {
      QUEUE.Push(
          HIDEBOX,
          ["resetEquationNumbers",MathJax.InputJax.TeX],
          ["Text",math,"\\displaystyle{"+TeX+"}"],
          SHOWBOX
      );
    }
  })();
</script>


<input id="MathInput" size="80" onchange="UpdateMath(this.value)" />

<div class="box" id="box" style="visibility:hidden">
<textarea id="MathOutput" class="output" name="txtSender">$${}$$</textarea>
</div>


<script>
  if (MathJax.Hub.Browser.isMSIE) {
    MathInput.onkeypress = function () {
      if (window.event && window.event.keyCode === 13) {this.blur(); this.focus()}
    }
  }
</script>

自定义JSON转换器:

[Serializable]
public class FileData
{
    private ContentType contentType;

    public ContentType ContentType
    {
        get { return contentType; }
        set { contentType = value; }
    }
}

转换器注册(public class ContentTypeJsonConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(ContentType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { return new ContentType((string)reader.Value); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { writer.WriteValue(((ContentType)value).ToString()); } } ):

WebApiConfig.cs

控制器:

public static void Register(HttpConfiguration config)
{
    ...
    config
        .Formatters
        .JsonFormatter
        .SerializerSettings
        .Converters
        .Add(new ContentTypeJsonConverter());
}

请求:

public class TestController : ApiController
{
    public IHttpActionResult Post(FileData data)
    {
        return this.Ok(data);
    }
}

响应:

POST /api/test HTTP/1.1
Content-Type: application/json
Host: localhost:48278
Content-Length: 36

{
    "contentType": "image/png"
}