如何让ASP.NET Web API使用Chrome返回JSON而不是XML?

如何让ASP.NET Web API使用Chrome返回JSON而不是XML?,json,google-chrome,asp.net-web-api,Json,Google Chrome,Asp.net Web Api,使用较新的ASP.NET Web API,在Chrome中,我看到了XML-如何将其更改为请求JSON,以便在浏览器中查看?我相信这只是请求头的一部分,我说的对吗?看看WebAPI中的内容协商。这些(&)非常详细和透彻的博客文章解释了它是如何工作的 简而言之,您是对的,只需设置Accept或Content-Type请求头。如果您的操作未编码为返回特定格式,则可以设置Accept:application/json 一个快速选项是使用MediaTypeMapping专门化。以下是在应用程序启动事件中

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

看看WebAPI中的内容协商。这些(&)非常详细和透彻的博客文章解释了它是如何工作的


简而言之,您是对的,只需设置
Accept
Content-Type
请求头。如果您的操作未编码为返回特定格式,则可以设置
Accept:application/json

一个快速选项是使用MediaTypeMapping专门化。以下是在应用程序启动事件中使用QueryStringMapping的示例:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a", "b", "application/json"));
现在,在本例中,每当url包含querystring?a=b时,浏览器中将显示Json响应。

我发现Chrome应用程序“高级REST客户端”非常适合与REST服务一起使用。您可以将内容类型设置为
application/json
,除此之外:

MVC4快速提示3–从ASP.Net Web API中删除XML格式化程序

Global.asax
中添加行:

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
像这样:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    BundleTable.Bundles.RegisterTemplateBundles();
    GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}

在Global.asax中,我使用下面的代码。我获取JSON的URI是
http://www.digantakumar.com/api/values?json=true

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new  QueryStringMapping("json", "true", "application/json"));
}

不要使用浏览器测试API

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


此问题的问题在于客户端,而不是API。web API根据浏览器的请求正确运行。

如果您在
WebApiConfig
中执行此操作,默认情况下将获得JSON,但如果您将
text/XML
作为请求
接受
头传递,它仍然允许您返回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项目类型,因此没有该类,请参阅如何合并它的详细信息。

我只需在我的MVCWeb API项目中的
App_Start/WebApiConfig.cs
类中添加以下内容

config.Formatters.JsonFormatter.SupportedMediaTypes
    .Add(new MediaTypeHeaderValue("text/html") );
这确保了在大多数查询中都可以获得JSON,但在发送
text/XML
时可以获得
XML

如果您需要将响应
内容类型
设置为
应用程序/json
请检查


NameSpace
正在使用
System.Net.Http.Headers

WebApiConfig.cs中,添加到Register函数的末尾:

// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);

.

用户代理
标题包含“Chrome”时,我使用全局操作筛选器删除
Accept:application/xml

内部类RemoveXmlForgogleChromeFilter:IActionFilter
{
公共布尔允许多个
{
获取{return false;}
}
公共异步任务ExecuteActionFilterAsync(
HttpActionContext操作上下文,
CancellationToken CancellationToken,
Func(续)
{
var userAgent=actionContext.Request.Headers.userAgent.ToString();
if(userAgent.Contains(“Chrome”))
{
var acceptHeaders=actionContext.Request.Headers.Accept;
变量头=
acceptHeaders.SingleOrDefault(
x=>x.MediaType.Contains(“application/xml”);
acceptHeaders.Remove(header);
}
返回等待继续();
}
}

这段代码使json成为我的默认值,并允许我使用XML格式。我将只添加
xml=true

GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "application/xml"));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

谢谢大家

由于问题是特定于Chrome的,您可以获得允许您设置请求内容类型的

我最喜欢——确保浏览器获得JSON,而不会影响实际需要XML的客户端的内容协商。我唯一缺少的是响应头仍然包含内容类型:text/html。为什么这是个问题?因为我使用了,它检查内容类型,我没有得到我习惯的漂亮格式。我使用一个简单的自定义格式化程序修复了这个问题,该格式化程序接受文本/html请求并返回应用程序/json响应:

public class BrowserJsonFormatter : JsonMediaTypeFormatter
{
    public BrowserJsonFormatter() {
        this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
        this.SerializerSettings.Formatting = Formatting.Indented;
    }

    public override void SetDefaultContentHeaders(Type type, HttpContentHeaders headers, MediaTypeHeaderValue mediaType) {
        base.SetDefaultContentHeaders(type, headers, mediaType);
        headers.ContentType = new MediaTypeHeaderValue("application/json");
    }
}
登记如下:

config.Formatters.Add(new BrowserJsonFormatter());

使用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"));

从MSDN开始(大约41分钟)


这应该是最新的,我试过了,效果很好。

我不清楚为什么答案如此复杂。当然有很多方法可以做到这一点,包括查询字符串、标题和选项。。。但我认为最好的做法很简单。您请求一个普通URL(例如:
http://yourstartup.com/api/cars
)作为回报,您将获得JSON。您可以使用正确的响应头获取JSON:

Content-Type: application/json
在寻找同一个问题的答案时,我找到了这个线索,并且不得不继续下去,因为这个被接受的答案并不完全有效。我确实找到了一个答案,我觉得这个答案太简单了,不是最好的:

我也会在这里加上我的小费

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默认值,或者可能是在其他地方创建的(由我的项目中的其他人创建的)。另外,希望这能有所帮助。

自提出(并回答)此问题以来,已经过了一段时间,但另一个选项是在请求处理过程中使用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);
    }
}
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
或以路线为基础:

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;
    }
}
public类ForceableContentTypeDelegationHand
config.Routes.MapHttpRoute(
   name: "SpecialContentRoute",
   routeTemplate: "api/someUrlThatNeedsSpecialTreatment/{id}",
   defaults: new { controller = "SpecialTreatment" id = RouteParameter.Optional },
   constraints: null,
   handler: new ForceableContentTypeDelegationHandler()
);
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;
    }
}
public static void Register(HttpConfiguration config)
{
    // add support for the 'format' query param
    // cref: http://blogs.msdn.com/b/hongyes/archive/2012/09/02/support-format-in-asp-net-web-api.aspx
    config.Formatters.JsonFormatter.AddQueryStringMapping("$format", "json", "application/json");
    config.Formatters.XmlFormatter.AddQueryStringMapping("$format", "xml", "application/xml");

    // ... additional configuration
 }
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}"
       );
    }
    var formatters = GlobalConfiguration.Configuration.Formatters;

    formatters.Remove(formatters.XmlFormatter);

    config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
public static class WebApiConfig
{
     public static void Register(HttpConfiguration config)
     {
          //add this two line 
          config.Formatters.Clear();
          config.Formatters.Add(new JsonMediaTypeFormatter());


          ............................
      }
}
public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        ...

        // Configure Web API to return JSON
        config.Formatters.JsonFormatter
        .SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("text/html"));

        ...
    }
}
public class JsonOutputAttribute : ActionFilterAttribute
{
    public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
    {
        ObjectContent content = actionExecutedContext.Response.Content as ObjectContent;
        var value = content.Value;
        Type targetType = actionExecutedContext.Response.Content.GetType().GetGenericArguments()[0];

        var httpResponseMsg = new HttpResponseMessage
        {
            StatusCode = HttpStatusCode.OK,
            RequestMessage = actionExecutedContext.Request,
            Content = new ObjectContent(targetType, value, new JsonMediaTypeFormatter(), (string)null)
        };

        actionExecutedContext.Response = httpResponseMsg;
        base.OnActionExecuted(actionExecutedContext);
    }
}
[JsonOutput]
public IEnumerable<Person> GetPersons()
{
    return _repository.AllPersons(); // the returned output will be in JSON
}
public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );                
            config.Formatters.Remove(config.Formatters.XmlFormatter);                
            config.EnableSystemDiagnosticsTracing();
        }
        config.Formatters.Remove(config.Formatters.XmlFormatter);
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());