我在ASP.Net中有一个WebAPI 2.0项目,我在其中实现了一个自定义的DefaultContractResolver,以便我可以控制我的实体如何使用JSON.Net序列化为JSON;但我不确定如何告诉框架使用我的自定义实现。我还想知道是否可以为特定的控制器/操作更改ContractResolver。
谢谢!
---编辑03/07/2014 我已经通过创建一个新的ConfigSettings对象并手动解析该对象,已经找到了如何使用我的自定义实现;但是,生成的JSON被序列化两次(它有额外的\ r \ n字符)。这是因为webAPI控制器默认序列化响应,所以我想更改以覆盖该行为......这是正确的方法吗?
答案 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的这篇文章非常有帮助。