如何让ASP.NET Web API使用Chrome返回JSON而不是XML?
使用较新的ASP.NET Web API,在Chrome中,我看到了XML-如何将其更改为请求JSON,以便在浏览器中查看?我相信这只是请求头的一部分,我说的对吗?看看WebAPI中的内容协商。这些(&)非常详细和透彻的博客文章解释了它是如何工作的如何让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专门化。以下是在应用程序启动事件中
简而言之,您是对的,只需设置
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());