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

nas*_*ski 1220 json google-chrome asp.net-web-api

使用较新的ASP.NET Web API,在Chrome中我看到了XML - 如何更改它以请求JSON,以便我可以在浏览器中查看它?我相信它只是请求标题的一部分,我是否正确?

Fel*_*sin 1695

我只是App_Start / WebApiConfig.cs在我的MVC Web API项目中添加以下内容.

config.Formatters.JsonFormatter.SupportedMediaTypes
    .Add(new MediaTypeHeaderValue("text/html") );
Run Code Online (Sandbox Code Playgroud)

这可以确保你在大多数查询中获得json,但是你可以xml在发送时获得text/xml.

如果您需要回复Content-Type,application/json请查看Todd的答案如下.

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

  • 这是一个令人惊讶的被忽视的答案,虽然原始问题并不完全清楚,但这直接使JSON成为Web浏览器的默认响应(发送Accept:text/html).做得好. (113认同)
  • 这太可怕了.响应内容类型标题应为application/json.这个"解决方案"使它成为text/html. (75认同)
  • 这个答案更好:http://stackoverflow.com/a/26068063/510149 (31认同)
  • 请注意,响应的`Content-Type`标题仍然是`text/html`. (23认同)
  • +1远离最好的答案.我想有很多人选择完全删除XML只是因为他们没有在浏览器中看到JSON. (15认同)
  • 我发现当我这样做时,由第三方提供的带有HTML中断标签的数据最终会带有回车.然后JSON无效.如果这会影响您,最好使用接受的答案. (3认同)
  • 如果您只想锁定到 json,我建议您清除所有格式化程序并仅启用 Json。`GlobalConfiguration.Configuration.Formatters.Clear();``GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());` (3认同)
  • 这个答案可能会暴露一个 XSS 漏洞。WebAPI 将在 404 响应中包含完整 URL,并且由于内容类型是 text/html,浏览器将很乐意执行查询字符串中包含的任何 JavaScript。 (3认同)
  • 我同意@meffect,这对于开发环境来说是一个“很好”的答案,但是如果您在生产环境中使用此解决方案,您将面临 XSS 攻击。 (3认同)
  • 正如其他人指出的那样,这会导致 Web api 404 页面上存在 XSS 漏洞,因为导致 404 的 URL 作为内容包含在 404 错误页面上。不使用。 (3认同)
  • 我有一段时间没有使用过WebAPI,但我很确定就是这样. (2认同)
  • 为什么text/html?不是json的类型:application/json?当我使用上面的解决方案并将application/json而不是text/html时,我得到了XML中的响应.这个计数器不直观吗?application/json应该有效.这是什么原因? (2认同)
  • 注意,如果_request_"Accept"头字段是"application/json"(即在ajax GET请求中设置),它应该返回json.我这样做但是如果你打开chrome中的url(其中request accept不设置为json),则会显示xml. (2认同)

Gle*_*ven 499

如果你这样做,WebApiConfig你将默认获得JSON,但如果你text/xml作为请求Accept头传递,它仍然允许你返回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);
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您没有使用MVC项目类型,因此没有开始使用此类,请参阅此答案以获取有关如何合并它的详细信息.

  • 需要注意的是,原始行为是正确的.Chrome请求`application/xml`优先级为0.9,而`*/*`优先级为0.8.通过删除`application/xml`,如果客户端专门请求,则删除Web API返回XML的能力.例如,如果您发送"Accept:application/xml",您将*仍然*收到JSON. (51认同)
  • 是我,还是第一句话不正确?该代码似乎完全删除了XML,而不是简单地更改默认值. (11认同)
  • @NickG:这里忽略了一个解决方案,恕我直言是一个更好的选择(保持application/xml)是Felipe Leusin在本页面下提出的解决方案.使用config.Formatters.XmlFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); (6认同)
  • @Felipse Leusin的答案实际上更短,效果更好. (4认同)

Tod*_*ier 303

我最喜欢Felipe Leusin的方法 - 确保浏览器获得JSON而不会影响实际需要XML的客户端的内容协商.对我来说唯一缺少的部分是响应头仍然包含content-type:text/html.为什么这是一个问题?因为我使用了JSON Formatter Chrome扩展程序,它检查内容类型,但我没有得到我习惯的漂亮格式.我修复了一个简单的自定义格式化程序,它接受text/html请求并返回application/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");
    }
}
Run Code Online (Sandbox Code Playgroud)

注册如下:

config.Formatters.Add(new BrowserJsonFormatter());
Run Code Online (Sandbox Code Playgroud)

  • 在构造函数中添加`this.SerializerSettings.Formatting = Formatting.Indented;`如果你想在没有浏览器扩展的情况下进行漂亮打印. (24认同)
  • 对于正在寻找的googlers:不要忘记添加`using System.Net.Http.Formatting`和`使用Newtonsoft.Json` (13认同)
  • 你为什么要把它打印在电线上呢? (10认同)
  • 是不是@dmit77的[答案](http://stackoverflow.com/a/26068063/532517)比这个更好(更简洁)? (8认同)
  • @eddiegroves你不希望通过电线漂亮打印.您希望服务器通过线路发送最少量的位(即:无空格).然后你希望浏览器使用插件等很好地格式化它.Javascript通常需要解析JSON,为什么通过引入不必要的格式化使它变慢 (8认同)
  • 谢谢托德,最佳答案:1)正确的返回类型,2)仅从浏览器保持漂亮的格式,3)我不必向 Firefox 添加新的接受类型,Chrome 也可以!甜蜜。 (2认同)

小智 300

使用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"));
Run Code Online (Sandbox Code Playgroud)

  • 为我工作.我需要使用System.Net.Http.Formatting添加**;** (9认同)
  • 它应该放在WebApiConfig.cs中 (8认同)
  • 这是最精简和最简单的解决方案,Fiddler还会检测作为josn返回的内容类型. (5认同)
  • 太好了!你会在哪里建议把它放在代码中? (3认同)
  • 需要明确的是,这只是更改默认值。您始终可以通过包含相关的“Accept”标头来获取 JSON 或 XML。 (2认同)

Yak*_*nor 185

MVC4快速提示#3 - 从ASP.Net Web API中删除XML Formatter

Global.asax添加一行:

GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
Run Code Online (Sandbox Code Playgroud)

像这样:

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

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

    BundleTable.Bundles.RegisterTemplateBundles();
    GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}
Run Code Online (Sandbox Code Playgroud)

  • 我测试了它,你不能.所以这是删除XML支持..你要警告,亲爱的谷歌人 (97认同)
  • Works - 使JSON成为默认值而不是XML更好. (9认同)
  • 但是你还能回复xml吗? (5认同)
  • 如果您查看下面的答案,如果您愿意,仍然会返回xml,但让网站使用JSON响应浏览器 (3认同)
  • @GlennSlaven是的,你的答案应该是标记为正确的答案. (3认同)

Mic*_*sky 115

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

// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
Run Code Online (Sandbox Code Playgroud)

来源.

  • 对于必须仅支持JSON的项目,在任何情况下都不允许发出XML,这是目前最好的选择. (4认同)
  • 这太可怕了. - 无论如何,这将始终返回JSON,即使客户端在Content-Type标头中特别要求XML. (3认同)
  • 没有像 JSON 版本那样彻底测试 API 的 XML 版本的项目应该选择此选项。根据 Michael 包含的链接,不同的格式化程序对对象进行不同的序列化。例如:XML 格式化程序不会序列化只读字段,而 JSON 格式化程序则会序列化。 (2认同)

Dig*_*mar 93

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"));
}
Run Code Online (Sandbox Code Playgroud)

  • 太棒了.你的方法对参数有什么期望?喜欢http:// localhost:61044/api/values/getdate?json = true,date = 2012-08-01 (2认同)

Aar*_*els 54

看看WebAPI中的内容协商.这些(第1部分第2部分)非常详细和全面的博客文章解释了它的工作原理.

简而言之,您是对的,只需要设置AcceptContent-Type请求标头.如果您的Action未编码为返回特定格式,则可以进行设置Accept: application/json.

  • "所以我可以在浏览器中查看它" (6认同)

Chr*_*s S 45

由于问题是特定于Chrome的,因此您可以获取Postman扩展程序,该扩展程序允许您设置请求内容类型.

邮差


suh*_*air 35

一个快速选项是使用MediaTypeMapping专门化.以下是在Application_Start事件中使用QueryStringMapping的示例:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a", "b", "application/json"));
Run Code Online (Sandbox Code Playgroud)

现在,只要url包含查询字符串?a = b,在这种情况下,Json响应将显示在浏览器中.

  • 这非常有用.如果要使用path.to/item.json,也可以使用UriPathExtensionMapping而不是QueryStringMapping. (2认同)

jay*_*eno 32

这段代码使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"));
Run Code Online (Sandbox Code Playgroud)

感谢大家!


小智 23

不要使用您的浏览器来测试您的API.

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

此问题的问题出在客户端,而不是API中.根据浏览器的请求,Web API行为正常.

  • 为什么不使用浏览器?它是一个明显的工具. (28认同)
  • 这应该是一个评论. (6认同)
  • 我认为这里的重点是正确和重要的 - 如果问题是由客户端引起的,我们不应该修复应用程序的工作部分(MVC WebAPI基础结构).Api的真实用例是正确使用(通过提供正确的标题),这是应用程序的责任.我不同意完全丢弃浏览器 - 为了测试,几乎所有浏览器都有很多工具(类似于Rest Client的扩展). (3认同)

pav*_*mar 17

大多数上述答案都非常有意义.由于您看到数据是以XML格式格式化的,这意味着应用了XML格式化程序,因此只需从HttpConfiguration参数中删除XMLFormatter即可看到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();
        }
Run Code Online (Sandbox Code Playgroud)

因为JSON是默认格式


Rog*_*mbe 12

Accept: application/xmlUser-Agent标题包含"Chrome" 时,我使用全局操作过滤器删除:

internal class RemoveXmlForGoogleChromeFilter : IActionFilter
{
    public bool AllowMultiple
    {
        get { return false; }
    }

    public async Task<HttpResponseMessage> ExecuteActionFilterAsync(
        HttpActionContext actionContext,
        CancellationToken cancellationToken,
        Func<Task<HttpResponseMessage>> continuation)
    {
        var userAgent = actionContext.Request.Headers.UserAgent.ToString();
        if (userAgent.Contains("Chrome"))
        {
            var acceptHeaders = actionContext.Request.Headers.Accept;
            var header =
                acceptHeaders.SingleOrDefault(
                    x => x.MediaType.Contains("application/xml"));
            acceptHeaders.Remove(header);
        }

        return await continuation();
    }
}
Run Code Online (Sandbox Code Playgroud)

似乎工作.


Mik*_*ley 11

我发现Chrome应用程序"高级REST客户端"非常适合使用REST服务.您可以将Content-Type设置为以下内容application/json: 高级REST客户端


Sta*_*ked 9

返回正确的格式由媒体类型格式化程序完成.正如其他人提到的,你可以在WebApiConfig课堂上做到这一点:

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

        ...
    }
}
Run Code Online (Sandbox Code Playgroud)

更多信息,请查看:

如果您的操作返回XML(默认情况下是这种情况),并且您只需要一个特定的方法来返回JSON,那么您可以使用ActionFilterAttribute并将其应用于该特定操作.

过滤属性:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

申请行动:

[JsonOutput]
public IEnumerable<Person> GetPersons()
{
    return _repository.AllPersons(); // the returned output will be in JSON
}
Run Code Online (Sandbox Code Playgroud)

请注意,您可以省略Attribute动作修饰上的单词,[JsonOutput]而不是使用[JsonOutputAttribute].


Nic*_*ick 6

我不清楚为什么答案中会包含所有这些复杂性。当然,可以使用QueryStrings,标头和选项有很多方法来实现此目的,但是我认为最好的做法很简单。您请求一个纯URL(例如:),http://yourstartup.com/api/cars然后返回JSON。您将获得带有正确响应标头的JSON:

Content-Type: application/json
Run Code Online (Sandbox Code Playgroud)

在寻找这个相同问题的答案时,我找到了这个线索,并且不得不继续前进,因为这个公认的答案无法正常工作。我确实找到了一个答案,我觉得这很简单,不能成为最佳答案:

设置默认的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());
}
Run Code Online (Sandbox Code Playgroud)

我确实有一个关于默认值(至少是我所看到的)来自何处的问题。它们是.NET默认值,还是在其他地方(由我项目中的其他人创建)创建。Anways,希望这会有所帮助。


小智 6

        config.Formatters.Remove(config.Formatters.XmlFormatter);
Run Code Online (Sandbox Code Playgroud)

  • 尽管此代码可以回答问题,但提供有关如何和/或为什么解决问题的其他上下文将提高​​答案的长期价值。请阅读此https://stackoverflow.com/help/how-to-answer (2认同)

小智 6

您可以使用如下:

GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
Run Code Online (Sandbox Code Playgroud)


mdi*_*bio 5

这是一个类似于jayson.centeno和其他答案的解决方案,但使用来自的内置扩展名System.Net.Http.Formatting

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
 }
Run Code Online (Sandbox Code Playgroud)

该解决方案主要是为了在WebApi的早期版本中为OData支持$ format,但它也适用于非OData实现,并Content-Type: application/json; charset=utf-8在响应中返回 标头。

使用浏览器进行测试时,它可让您补充&$format=json&$format=xml结束uri。使用非浏览器客户端可以在其中设置自己的标头时,它不会干扰其他预期行为。


A.T*_*.T. 5

按照最新版本的ASP.net WebApi 2,

在下WebApiConfig.cs,这将工作

config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
Run Code Online (Sandbox Code Playgroud)


Md.*_*med 5

只需在您的WebApiConfig类中 添加这两行代码

public static class WebApiConfig
{
     public static void Register(HttpConfiguration config)
     {
          //add this two line 
          config.Formatters.Clear();
          config.Formatters.Add(new JsonMediaTypeFormatter());


          ............................
      }
}
Run Code Online (Sandbox Code Playgroud)