更新:我已经上传了一个小测试项目到 github:链接
我正在使用 .Net Core 2 创建一个小型 Web 服务,并希望让客户能够指定他们是否需要响应中的导航信息。web api 应该只支持 xml 和 json,但是如果客户端可以在他们的请求中使用 Accept: application/xml+hateoas 或 Accept: application/json+hateoas 那就更好了。
我尝试像这样设置我的 AddMvc 方法:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(options =>
{
options.RespectBrowserAcceptHeader = true;
options.ReturnHttpNotAcceptable = true;
options.FormatterMappings.SetMediaTypeMappingForFormat(
"xml", MediaTypeHeaderValue.Parse("application/xml"));
options.FormatterMappings.SetMediaTypeMappingForFormat(
"json", MediaTypeHeaderValue.Parse("application/json"));
options.FormatterMappings.SetMediaTypeMappingForFormat(
"xml+hateoas", MediaTypeHeaderValue.Parse("application/xml"));
options.FormatterMappings.SetMediaTypeMappingForFormat(
"json+hateoas", MediaTypeHeaderValue.Parse("application/json"));
})
.AddJsonOptions(options => {
// Force Camel Case to JSON
options.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
})
.AddXmlSerializerFormatters()
.AddXmlDataContractSerializerFormatters()
;
我在我的控制器方法中使用接受标头来区分正常的 xml/json 响应和类似讨厌的响应,如下所示:
[HttpGet]
[Route("GetAllSomething")]
public async Task<IActionResult> GetAllSomething([FromHeader(Name = "Accept")]string accept)
{
...
bool generateLinks = !string.IsNullOrWhiteSpace(accept) && accept.ToLower().EndsWith("hateoas");
...
if (generateLinks)
{
AddNavigationLink(Url.Link("GetSomethingById", new { Something.Id }), "self", "GET");
}
...
}
所以,简而言之,我不想创建自定义格式化程序,因为唯一的“自定义”事情是在我的响应中包含或排除导航链接,但响应本身应该是基于 Accept 标头值的 xml 或 json。
我的模型类看起来像这样(主要是字符串和基本值):
[DataContract]
public class SomethingResponse
{
[DataMember]
public int Id { get; private set; }
从 Fiddler 调用我的服务时,我得到了不同 Accept 值的以下结果:
- 接受:application/json -> 状态码 200,仅包含请求的数据。
- 接受:application/json+hateoas -> 状态码 406(不可接受)。
- 接受:应用程序/xml -> 状态码 504。 [Fiddler] ReadResponse() 失败:服务器没有为此请求返回完整的响应。服务器返回 468 字节。
- 接受:application/xml+hateoas -> 状态码 406(不可接受)。
谁能告诉我哪个设置错了?