这个问题的答案是社区的努力。编辑现有答案以改进这篇文章。它目前不接受新的答案或交互。
使用较新的 ASP.NET Web API,在 Chrome 中我看到 XML - 如何将其更改为请求 JSON,以便我可以在浏览器中查看它?我确实相信它只是请求标头的一部分,我是否正确?
注意:阅读此答案的评论,如果您使用 WebAPI 的默认错误处理,它可能会产生 XSS 漏洞
我只是在我的 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
。
如果您在 WebApiConfig
中执行此操作,您将默认获得 JSON,但如果您将 text/xml
作为请求 Accept
标头传递,它仍然允许您返回 XML。
注意:这删除了对 application/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了解有关如何合并它的详细信息。
application/xml
和优先级为 0.8 的 */*
。通过删除 application/xml
,您将删除 Web API 在客户端特别请求时返回 XML 的能力。例如,如果您发送“Accept: application/xml”,您将仍然收到 JSON。
使用 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"));
我最喜欢Felipe Leusin's approach - 确保浏览器获取 JSON,而不会影响来自实际需要 XML 的客户端的内容协商。对我来说唯一缺少的是响应标头仍然包含内容类型: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());
this.SerializerSettings.Formatting = Formatting.Indented;
。
using System.Net.Http.Formatting
和using Newtonsoft.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();
}
在 WebApiConfig.cs 中,在 Register 函数的末尾添加:
// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
在 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"));
}
看看 WebAPI 中的内容协商。这些 (Part 1 & Part 2) 非常详细和透彻的博客文章解释了它的工作原理。
简而言之,您是对的,只需要设置 Accept
或 Content-Type
请求标头即可。鉴于您的操作未编码为返回特定格式,您可以设置 Accept: application/json
。
由于问题是特定于 Chrome 的,您可以获得 Postman extension,它允许您设置请求内容类型。
https://i.stack.imgur.com/A4GfR.png
network.http.accept.default
配置的内容更改为 text/html,application/xhtml+xml,application/json;q=0.9,application/xml;q=0.8,*/*;q=0.7
。
text/html,application/xhtml+xml;q=1.0,*/*;q=0.7
即可避免有问题的主机(例如 Bitbucket)意外地为您的浏览器提供 JSON 来代替 HTML。
此代码使 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"));
感谢大家!
一种快速的选择是使用 MediaTypeMapping 专业化。以下是在 Application_Start 事件中使用 QueryStringMapping 的示例:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a", "b", "application/json"));
现在,只要 url 在这种情况下包含查询字符串 ?a=b,Json 响应就会显示在浏览器中。
不要使用您的浏览器来测试您的 API。
相反,请尝试使用允许您指定请求的 HTTP 客户端,例如 CURL,甚至 Fiddler。
这个问题的问题在于客户端,而不是 API。根据浏览器的请求,Web API 行为正确。
上面的大多数答案都很有意义。由于您看到数据以 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 是默认格式
返回正确的格式由媒体类型格式化程序完成。正如其他人提到的,您可以在 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"));
...
}
}
有关更多信息,请查看:
ASP.NET Web API 2 中的媒体格式化程序。
ASP.NET Web API 中的内容协商。
如果您的操作返回 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);
}
}
适用于行动:
[JsonOutput]
public IEnumerable<Person> GetPersons()
{
return _repository.AllPersons(); // the returned output will be in JSON
}
请注意,您可以省略动作装饰中的 Attribute
一词,而只使用 [JsonOutput]
而不是 [JsonOutputAttribute]
。
当 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();
}
}
似乎工作。
我发现 Chrome 应用程序“高级 REST 客户端”非常适合与 REST 服务一起使用。您可以将 Content-Type 设置为 application/json
等:Advanced REST client
config.Formatters.Remove(config.Formatters.XmlFormatter);
在最新版本的 ASP.net WebApi 2 中,在 WebApiConfig.cs
下,这将起作用:
config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
我不清楚为什么答案中存在所有这些复杂性。当然有很多方法可以做到这一点,使用 QueryStrings、标题和选项......但我认为最佳实践很简单。您请求一个纯 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 默认值,还是可能在其他地方创建(由我项目中的其他人创建)。无论如何,希望这会有所帮助。
您可以使用如下:
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
这是一个类似于 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 的 $format,但它也适用于非 OData 实现,并在响应中返回 Content-Type: application/json; charset=utf-8
标头。
它允许您在使用浏览器进行测试时将 &$format=json
或 &$format=xml
添加到 uri 的末尾。使用可以设置自己的标头的非浏览器客户端时,它不会干扰其他预期行为。
只需在您的 WebApiConfig 类上添加这两行代码
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//add this two line
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
............................
}
}
您只需像这样更改 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}"
);
}
自从提出(并回答)这个问题以来已经过去了一段时间,但另一个选择是在请求处理期间使用 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;
}
}
这是我在应用程序中使用的最简单的方法。在 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,并且在标头中添加 application/json
,以便浏览器或接收器了解您正在返回 JSON 结果。
从 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();
}
它应该是最新的,我试过了,它奏效了。
多年来使用 Felipe Leusin 的答案,在最近更新核心库和 Json.Net 之后,我遇到了 System.MissingMethodException
:SupportedMediaTypes。就我而言,希望对遇到同样意外异常的其他人有所帮助的解决方案是安装 System.Net.Http
。 NuGet 在某些情况下显然会删除它。手动安装后,问题解决。
WebApiConfig 是您可以配置是否要以 json 或 xml 输出的地方。默认情况下,它是 xml。在 register 函数中,我们可以使用 HttpConfiguration Formatters 来格式化输出。
System.Net.Http.Headers => MediaTypeHeaderValue("text/html")
是获取 json 格式的输出所必需的。
https://i.stack.imgur.com/n3ksj.png
我很惊讶地看到如此多的回复需要编码来更改一个 API 中的单个用例 (GET),而不是使用必须安装一次且可用于任何 API(自己或第 3 方)和所有 API 的适当工具用例。
所以好的答案是:
如果您只想请求 json 或其他内容类型,请安装 Requestly 或类似工具并修改 Accept 标头。如果您也想使用 POST 并且有格式良好的 json、xml 等,请使用适当的 API 测试扩展,如 Postman 或 ARC。
Content-Type
标头仍为text/html
。