How do I get ASP.NET Web API to return JSON instead of XML using Chrome?
使用更新的ASP.NET Web API,在Chrome中,我看到的是XML——如何将其更改为请求JSON,以便在浏览器中查看它?我相信这只是请求头的一部分,我说的对吗?
我只是在我的MVC Web API项目中的
1 2 | config.Formatters.JsonFormatter.SupportedMediaTypes .Add(new MediaTypeHeaderValue("text/html") ); |
这可以确保您在大多数查询中都获得JSON,但在发送
如果您需要将
如果在
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | 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项目类型,因此没有这个类作为开始,请参阅这个答案,以了解有关如何合并它的详细信息。
我最喜欢Felipe Leucin的方法——确保浏览器获得JSON,而不影响真正需要XML的客户机的内容协商。我唯一缺少的是响应头仍然包含内容类型:text/html。为什么会有问题?因为我使用了JSON格式化程序chrome扩展,它检查内容类型,而且我没有得到我习惯的格式。我用一个简单的自定义格式化程序修复了这个问题,它接受文本/HTML请求并返回application/json响应:
1 2 3 4 5 6 7 8 9 10 11 12 | 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"); } } |
这样注册:
1 | config.Formatters.Add(new BrowserJsonFormatter()); |
使用requestheadermapping的效果更好,因为它还将响应头中的
1 2 3 4 5 6 | GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings .Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept", "text/html", StringComparison.InvariantCultureIgnoreCase, true, "application/json")); |
MVC4快速提示3–从ASP.NET Web API中删除XML格式化程序
在
1 | GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); |
像这样:
1 2 3 4 5 6 7 8 9 10 | protected void Application_Start() { AreaRegistration.RegisterAllAreas(); RegisterGlobalFilters(GlobalFilters.Filters); RegisterRoutes(RouteTable.Routes); BundleTable.Bundles.RegisterTemplateBundles(); GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear(); } |
在webapiconfig.cs中,添加到register函数的末尾:
1 2 | // Remove the XML formatter config.Formatters.Remove(config.Formatters.XmlFormatter); |
来源。
在global.asax中,我使用下面的代码。我得到JSON的URI是
1 2 3 4 5 6 7 8 9 10 | 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")); } |
看看WebAPI中的内容协商。这些(第1部分和第2部分)非常详细和彻底的博客文章解释了它是如何工作的。
简而言之,您是对的,只需要设置
由于这个问题是特定于chrome的,所以您可以获得postman扩展,它允许您设置请求内容类型。
一个快速的选项是使用mediatypemapping专门化。以下是在应用程序启动事件中使用QueryStringMapping的示例:
1 | GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a","b","application/json")); |
现在,每当URL包含查询字符串时?在这种情况下,JSON响应将显示在浏览器中。
这段代码使JSON成为我的默认值,并允许我使用XML格式。我就在后面加上
1 2 | GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml","true","application/xml")); GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); |
谢谢大家!
不要使用浏览器来测试API。
相反,尝试使用允许您指定请求的HTTP客户机,例如curl,甚至fiddler。
这个问题的问题在客户端,而不是在API中。根据浏览器的请求,Web API的行为正确。
以上大多数答案都是完全合理的。因为您看到的数据是以XML格式格式化的,这意味着应用了XML格式化程序,所以您只需从httpconfiguration参数中删除xml formatter即可看到json格式,如
1 2 3 4 5 6 7 8 9 10 | 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是默认格式
当
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | 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(); } } |
似乎起作用了。
我发现Chrome应用程序"高级REST客户端"非常适合使用REST服务。您可以将内容类型设置为
返回正确的格式是由媒体类型格式化程序完成的。正如其他人提到的,您可以在
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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")); ... } } |
有关更多信息,请查看:
- ASP.NET Web API 2中的媒体格式化程序。
- ASP.NET Web API中的内容协商。
如果您的操作返回XML(默认情况下是这样),并且您只需要一个特定的方法来返回JSON,那么您可以使用
筛选器属性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | 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); } } |
应用于操作:
1 2 3 4 5 | [JsonOutput] public IEnumerable<Person> GetPersons() { return _repository.AllPersons(); // the returned output will be in JSON } |
注意,你可以省略动作装饰上的
我不清楚为什么答案如此复杂。当然,有很多方法可以做到这一点,包括查询字符串、头和选项…但我认为最好的做法很简单。您请求一个普通的URL(例如:
1 | Content-Type: application/json |
在寻找同一个问题的答案时,我发现了这条线索,必须继续下去,因为这个公认的答案并不完全有效。我确实找到了一个答案,我觉得这个答案太简单了,不可能是最好的答案:
设置默认的WebAPI格式化程序
我也在这里加小费。
1 2 3 4 5 6 7 8 9 10 | 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默认值,还是在其他地方创建的(由我项目中的其他人创建的)。安威,希望这有帮助。
这里有一个类似于jayson.centeno和其他答案的解决方案,但是使用了
1 2 3 4 5 6 7 8 9 | 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的$format,但它也适用于非OData实现,并返回响应中的
当使用浏览器进行测试时,它允许您将
根据最新版本的ASP.NET WebAPI 2,
在
1 2 | config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter); config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter); |
1 | config.Formatters.Remove(config.Formatters.XmlFormatter); |
你只需要像这样改变
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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}" ); } |
只需在webapiconfig类中添加这两行代码
1 2 3 4 5 6 7 8 9 10 11 12 | public static class WebApiConfig { public static void Register(HttpConfiguration config) { //add this two line config.Formatters.Clear(); config.Formatters.Add(new JsonMediaTypeFormatter()); ............................ } } |
您可以如下使用:
1 2 | GlobalConfiguration.Configuration.Formatters.Clear(); GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter()); |
自从这个问题被提出(和回答)以来已经过了一段时间,但是另一个选项是在请求处理期间使用下面的消息处理程序重写服务器上的accept头:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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); } } |
其中
当然,你需要登记。您可以全局执行此操作:
1 2 3 | public static void Register(HttpConfiguration config) { config.MessageHandlers.Add(new ForceableContentTypeDelegationHandler()); } |
或按路线排列:
1 2 3 4 5 6 7 | config.Routes.MapHttpRoute( name:"SpecialContentRoute", routeTemplate:"api/someUrlThatNeedsSpecialTreatment/{id}", defaults: new { controller ="SpecialTreatment" id = RouteParameter.Optional }, constraints: null, handler: new ForceableContentTypeDelegationHandler() ); |
而且由于这是一个消息处理程序,它将在管道的请求端和响应端上运行,非常类似于
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | 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; } } |
下面是我在应用程序中使用的最简单的方法。在
1 2 3 4 5 | var formatters = GlobalConfiguration.Configuration.Formatters; formatters.Remove(formatters.XmlFormatter); config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json")); |
ASP.NET Web API将自动将返回的对象序列化到JSON,并且在头中添加了
从msdn构建一个带有ASP.NET和AngularJS的单页应用程序(大约41分钟)。
1 2 3 4 5 6 7 8 9 10 11 | 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(); } |
它应该是最新的,我试过了,它起作用了。
在最近更新了核心库和json.net之后,使用Felipe Leucin多年的答案,我遇到了一个
webapiconfig是一个可以配置以JSON还是XML形式输出的地方。默认情况下,它是XML。在register函数中,我们可以使用httpconfiguration格式化程序来格式化输出。system.net.http.headers=>mediatypeheadervalue("text/html")需要以JSON格式获取输出。
我很惊讶看到这么多的回复需要编码来改变一个API中的一个用例(GET),而不是使用一个必须安装一次的合适工具,并且可以用于任何API(自己的或第三方的)和所有用例。
所以好的答案是: