首页 文章

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

提问于
浏览
1221

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

29 回答

  • 257

    您可以使用如下:

    GlobalConfiguration.Configuration.Formatters.Clear();
    GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
    
  • 479

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

    我很惊讶地看到如此多的回复要求编码在一个API中更改单个用例(GET),而不是使用必须安装一次的适当工具,并且可以用于任何API(自己的或第三方)和所有用例 .

    所以好的答案是:

    • 如果您只想请求json或其他内容类型,请安装Requestly或类似工具并修改Accept标头 .

    • 如果你也想使用POST并且格式很好的json,xml等,请使用适当的API测试扩展,例如PostmanARC .

  • 4

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

    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();
    }
    
  • 3

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

    Postman

  • 2

    我发现Chrome应用程序"Advanced REST Client"非常适合使用REST服务 . 您可以将Content-Type设置为 application/json 以及其他内容:Advanced REST client

  • 7

    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"));
    }
    
  • 104

    这段代码使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"));
    

    感谢大家!

  • 88

    只需在 WebApiConfig 类上添加这两行代码即可

    public static class WebApiConfig
    {
         public static void Register(HttpConfiguration config)
         {
              //add this two line 
              config.Formatters.Clear();
              config.Formatters.Add(new JsonMediaTypeFormatter());
    
    
              ............................
          }
    }
    
  • 5
    config.Formatters.Remove(config.Formatters.XmlFormatter);
    
  • 0

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

    config.Formatters.JsonFormatter.SupportedMediaTypes
        .Add(new MediaTypeHeaderValue("text/html") );
    

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

    如果您需要将响应 Content-Type 设为 application/json ,请检查Todd's answer below .

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

  • 0

    WebApiConfig是您可以配置是否要以json或xml输出的位置 . 默认情况下它是xml . 在寄存器功能中,我们可以使用HttpConfiguration Formatters来格式化输出 . 需要System.Net.Http.Headers => MediaTypeHeaderValue("text/html")来获取json格式的输出 .

  • 28

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

    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();
        }
    }
    

    似乎工作 .

  • 40

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

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

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

  • 176

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

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

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

  • 2

    我最喜欢Felipe Leusin's approach - 确保浏览器获得JSON而不会影响实际需要XML的客户端的内容协商 . 对我来说唯一缺少的部分是响应头仍然包含content-type:text / html . 为什么这是一个问题?因为我使用JSON Formatter Chrome extension,它检查内容类型,我不习惯 . 我修复了一个简单的自定义格式化程序,它接受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");
        }
    }
    

    注册如下:

    config.Formatters.Add(new BrowserJsonFormatter());
    
  • -3

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

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

  • 50

    返回正确的格式由媒体类型格式化程序完成 . 正如其他人提到的,您可以在 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"));
    
            ...
        }
    }
    

    有关更多信息,请查看

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

    Filter attribute:

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

    Applying to action:

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

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

  • 32

    多年来使用 Felipe Leusin 的答案,在最近更新了核心库和Json.Net之后,我遇到了 System.MissingMethodException :SupportedMediaTypes . 在我的情况下,希望对遇到相同意外异常的其他人有帮助的解决方案是安装 System.Net.Http . 在某些情况下,NuGet显然会删除它 . 手动安装后,问题得以解决 .

  • 1

    这个问题已经过了一段时间了问(并回答)但另一个选择是在请求处理期间使用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;
        }
    }
    
  • 0

    我不清楚为什么答案中存在所有这些复杂性 . 当然,有很多方法可以做到这一点,使用QueryStrings, Headers 和选项...但我认为最好的做法很简单 . 您请求一个普通的URL(例如: http://yourstartup.com/api/cars ),作为回报,您获得JSON . 你得到JSON正确的响应头:

    Content-Type: application/json
    

    在寻找这个相同问题的答案时,我找到了这个帖子,并且必须继续前进,因为这个接受的答案并不完全正常 . 我确实找到了一个答案,我觉得这个答案太简单了,不是最好的答案:

    Set the default WebAPI formatter

    我也会在这里添加我的提示 .

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

  • 11

    这是我在我的应用程序中使用的最简单方法 . 在 Register 函数的 App_Start\\WebApiConfig.cs 中添加以下3行代码

    var formatters = GlobalConfiguration.Configuration.Formatters;
    
        formatters.Remove(formatters.XmlFormatter);
    
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
    

    Asp.net web API会自动将您返回的对象序列化为JSON,并且在 Headers 中添加了 application/json ,以便浏览器或接收者了解您正在返回JSON结果 .

  • 3

    MSDN Building a Single Page Application with ASP.NET and AngularJS(约41分钟) .

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // ... possible routing etc.
    
            // Setup to return json and camelcase it!
            var formatter = GlobalConfiguration.Configuration.Formatters.JsonFormatter;
            formatter.SerializerSettings.ContractResolver =
                new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
        }
    

    它应该是最新的,我尝试了它并且它起作用了 .

  • 1

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

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

    Source .

  • 18

    上述大多数答案都非常有意义 . 由于您看到数据是以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();
            }
    

    因为JSON是默认格式

  • 1587

    这是一个类似于jayson.centeno's和其他答案的解决方案,但使用了 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
     }
    

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

    它允许您在使用浏览器进行测试时将 &$format=json&$format=xml 添加到uri的末尾 . 使用非浏览器客户端时,它不会干扰其他预期的行为,您可以在其中设置自己的标头 .

  • 2

    根据最新版本的ASP.net WebApi 2,

    WebApiConfig.cs 下,这将有效

    config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
    config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
    
  • 8

    如果在 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);
        }
    }
    

    如果您没有使用MVC项目类型,因此没有开始使用此类,see this answer有关如何合并它的详细信息 .

  • 1

    你只需改变 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}"
           );
        }
    

相关问题