我应该在哪里插入我的自定义DefaultContractResolver JSON.NET?

时间:2014-07-03 00:56:38

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

我在ASP.Net中有一个WebAPI 2.0项目,我在其中实现了一个自定义的DefaultContractResolver,以便我可以控制我的实体如何使用JSON.Net序列化为JSON;但我不确定如何告诉框架使用我的自定义实现。我还想知道是否可以为特定的控制器/操作更改ContractResolver。

谢谢!

---编辑03/07/2014 我已经通过创建一个新的ConfigSettings对象并手动解析该对象,已经找到了如何使用我的自定义实现;但是,生成的JSON被序列化两次(它有额外的\ r \ n字符)。这是因为webAPI控制器默认序列化响应,所以我想更改以覆盖该行为......这是正确的方法吗?

2 个答案:

答案 0 :(得分:3)

我只是经历了自己搞清楚的痛苦,我需要一个按照要求工作的东西。您可以使用该方法并返回相同的媒体格式化程序。我发现在GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.ContractResolver上设置格式化程序对于每个请求的需求有点不可靠,即使我尝试在该类的单个实例中处理每个请求的需求。但是,您可以尝试在App_Start代码中的某处设置ContractResolver实例

我最终创建了一个自定义JsonMediaTypeFormatter,用于检查是否为请求配置了ContractResolver,您只需返回一个相同的解析器:

public class DynamicJsonMediaTypeFormatter : JsonMediaTypeFormatter
{ 
public override MediaTypeFormatter GetPerRequestFormatterInstance(Type type, System.Net.Http.HttpRequestMessage request, System.Net.Http.Headers.MediaTypeHeaderValue mediaType)
{
// shown is getting the current formatter, but you can return an instance you prefer
  var formatter = base.GetPerRequestFormatterInstance(type, request, mediaType) as JsonMediaTypeFormatter; 

// Here I had more code to get the resolver based on request, skipped
  ((JsonMediaTypeFormatter)formatter).SerializerSettings.ContractResolver = <YourContractResolverInstance>;
    return formatter;
}
}

我认为你已经想出了那个部分,但是你的合同解析器可以覆盖`CreateProperties'并且有你自己的逻辑决定将出现什么json属性以及它们将使用什么名称(为了其他读者的完整性和好处而添加) :

public class DynamicContractResolver : DefaultContractResolver
{
...
 protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization){
  ...
}

答案 1 :(得分:1)

我最终改变了我的方法的返回类型:

假设我们有这个简单的Foo类:

public class Foo
{
    public string Bar {get; set;}
}

使用ASP WebApi 2.0,GET的脚手架控制器方法如下所示:

// GET api/Foo
public IQueryable<Foo> GetFoos()
{
    var foos = GetAListOfFoosFromSomewhere() //returns an IQueryable<Foo>
    return Foos
}

请注意,框架会自动将Foos序列化为JSON。

所以我所做的就是将方法更改为:

// GET api/Foo
public HttpResponseMessage GetFoos()
{
    var foos = GetAListOfFoosFromSomewhere(); //returns an IQueryable<Foo>
    var settings = new JsonSerializerSettings()
    {
     ContractResolver= new MyCustomContractResolver(), //Put  your custom implementation here
     //Also set up ReferenceLoopHandling as appropiate
    };
    var jsoncontent = JsonConvert.SerializeObject(foos, settings);
    var response = new HttpResponseMessage(HttpStatusCode.OK)
    {
        Content = new StringContent(jsoncontent, Encoding.UTF8, "application/json")
    };
    return response;
}

在我的解决方案中,我添加了一个convience方法来创建HttpResponseMessage,所以看起来有点像这样:

public HttpResponseMessage GetFoos()
{
    var foos = GetAListOfFoosFromSomewhere() //returns an IQueryable<Foo>
    return CreateResponse(foos);
}

mercury2269的这篇文章非常有帮助。