使用更新的ASP。NET Web API,在Chrome中我看到XML -我如何将其更改为请求JSON,以便我可以在浏览器中查看它?我相信这只是请求头的一部分,我是正确的吗?


当前回答

我不清楚为什么答案会这么复杂。当然,有很多方法可以做到这一点,QueryStrings,头和选项…但我认为最好的做法很简单。你请求一个简单的URL(例如:http://yourstartup.com/api/cars),作为回报,你得到JSON。你得到JSON和适当的响应头:

Content-Type: application/json

在寻找这个问题的答案时,我发现了这个帖子,并不得不继续下去,因为这个公认的答案并不完全正确。我确实找到了一个答案,我觉得它太简单了,不是最好的答案:

设置默认的WebAPI格式化程序

我把我的小费也加在这里。

WebApiConfig.cs

namespace com.yourstartup
{
  using ...;
  using System.Net.Http.Formatting;
  ...
  config.Formatters.Clear(); //because there are defaults of XML..
  config.Formatters.Add(new JsonMediaTypeFormatter());
}

我确实有一个问题,默认(至少我看到的那些)来自哪里。它们是. net默认的,还是在其他地方创建的(由我项目中的其他人创建)。无论如何,希望这能有所帮助。

其他回答

你只需要像这样修改App_Start/WebApiConfig.cs:

public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        // Web API routes
        config.MapHttpAttributeRoutes();
        //Below formatter is used for returning the Json result.
        var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
        config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
        //Default route
        config.Routes.MapHttpRoute(
           name: "ApiControllerOnly",
           routeTemplate: "api/{controller}"
       );
    }

从这个问题被问到(和回答)已经过去了一段时间,但是另一个选择是在请求处理过程中使用MessageHandler覆盖服务器上的Accept头,如下所示:

public class ForceableContentTypeDelegationHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
                HttpRequestMessage request,
                CancellationToken cancellationToken)
    {
        var someOtherCondition = false;
        var accHeader = request.Headers.GetValues("Accept").FirstOrDefault();
        if (someOtherCondition && accHeader.Contains("application/xml"))
        {
            request.Headers.Remove("Accept");
            request.Headers.Add("Accept", "application/json");
        }
        return await base.SendAsync(request, cancellationToken);
    }
}

其中someOtherCondition可以是任何东西,包括浏览器类型等。这将用于有条件的情况,即有时我们只想覆盖默认的内容协商。否则,根据其他答案,您只需从配置中删除一个不必要的格式化程序。

当然你需要注册。你可以全局执行:

  public static void Register(HttpConfiguration config) {
      config.MessageHandlers.Add(new ForceableContentTypeDelegationHandler());
  }

或按路线划分:

config.Routes.MapHttpRoute(
   name: "SpecialContentRoute",
   routeTemplate: "api/someUrlThatNeedsSpecialTreatment/{id}",
   defaults: new { controller = "SpecialTreatment" id = RouteParameter.Optional },
   constraints: null,
   handler: new ForceableContentTypeDelegationHandler()
);

由于这是一个消息处理程序,它将运行在管道的请求端和响应端,就像HttpModule一样。所以你可以很容易地用一个自定义头来确认覆盖:

public class ForceableContentTypeDelegationHandler : DelegatingHandler
{
    protected async override Task<HttpResponseMessage> SendAsync(
                HttpRequestMessage request,
                CancellationToken cancellationToken)
    {
        var wasForced = false;
        var someOtherCondition = false;
        var accHeader = request.Headers.GetValues("Accept").FirstOrDefault();
        if (someOtherCondition && accHeader.Contains("application/xml"))
        {
            request.Headers.Remove("Accept");
            request.Headers.Add("Accept", "application/json");
            wasForced = true;
        }

        var response =  await base.SendAsync(request, cancellationToken);
        if (wasForced){
          response.Headers.Add("X-ForcedContent", "We overrode your content prefs, sorry");
        }
        return response;
    }
}

不要使用浏览器来测试API。

相反,尝试使用允许您指定请求的HTTP客户机,例如CURL,甚至Fiddler。

这个问题的问题在客户端,而不是API。web API根据浏览器的请求正确地工作。

如果你在WebApiConfig中这样做,默认情况下你会得到JSON,但是如果你传递text/ XML作为请求Accept头,它仍然允许你返回XML。

注意:这删除了对application/xml的支持

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );

        var appXmlType = config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml");
        config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(appXmlType);
    }
}

如果你不使用MVC项目类型,因此没有这个类开始,请参阅这个答案关于如何合并它的详细信息。

使用RequestHeaderMapping工作得更好,因为它还在响应头中设置Content-Type = application/json,这允许Firefox(带有JSONView插件)将响应格式化为json。

GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings
.Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept", 
                              "text/html",
                              StringComparison.InvariantCultureIgnoreCase,
                              true, 
                              "application/json"));