Utilizando la API web ASP.NET más reciente , en Chrome veo XML: ¿cómo puedo cambiarlo para solicitar JSON para poder verlo en el navegador? Creo que es solo parte de los encabezados de solicitud, ¿estoy en lo cierto?
Utilizando la API web ASP.NET más reciente , en Chrome veo XML: ¿cómo puedo cambiarlo para solicitar JSON para poder verlo en el navegador? Creo que es solo parte de los encabezados de solicitud, ¿estoy en lo cierto?
Respuestas:
Solo agrego lo siguiente en App_Start / WebApiConfig.cs
clase en mi proyecto MVC Web API .
config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("text/html") );
Eso asegura que obtenga JSON en la mayoría de las consultas, pero puede obtenerlo XML
cuando envía text/xml
.
Si es necesario tener la respuesta Content-Type
que application/json
por favor verifica la respuesta de Todd a continuación .
NameSpace
está utilizando System.Net.Http.Headers
.
Content-Type
encabezado de la respuesta seguirá siendo text/html
.
Si hace esto en el WebApiConfig
, obtendrá JSON de forma predeterminada, pero aún le permitirá devolver XML si pasa text/xml
como Accept
encabezado de solicitud
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);
}
}
Si no está utilizando el tipo de proyecto MVC y, por lo tanto, no tenía esta clase para comenzar, consulte esta respuesta para obtener detalles sobre cómo incorporarlo.
application/xml
tienen una prioridad de 0.9 y */*
una prioridad de 0.8. Al eliminar application/xml
, elimina la capacidad de la API web de devolver XML si el cliente lo solicita específicamente. por ejemplo, si se envía "Accept: application / xml" le sigue recibir JSON.
El uso de RequestHeaderMapping funciona aún mejor, porque también establece el Content-Type = application/json
encabezado en la respuesta, lo que permite que Firefox (con el complemento JSONView) formatee la respuesta como JSON.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings
.Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept",
"text/html",
StringComparison.InvariantCultureIgnoreCase,
true,
"application/json"));
Me gusta más el enfoque de Felipe Leusin : asegúrese de que los navegadores obtengan JSON sin comprometer la negociación de contenido de los clientes que realmente desean XML. Lo único que me faltaba era que los encabezados de respuesta todavía contenían tipo de contenido: texto / html. ¿Por qué fue eso un problema? Porque uso la extensión JSON Formatter Chrome , que inspecciona el tipo de contenido, y no obtengo el formato bonito al que estoy acostumbrado. Lo arreglé con un formateador personalizado simple que acepta solicitudes de texto / html y devuelve respuestas de aplicación / 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");
}
}
Regístrese así:
config.Formatters.Add(new BrowserJsonFormatter());
this.SerializerSettings.Formatting = Formatting.Indented;
si desea que esté bien impreso sin una extensión de navegador.
using System.Net.Http.Formatting
yusing Newtonsoft.Json
MVC4 Consejo rápido # 3: eliminar el formateador XML de la API web ASP.Net
En Global.asax
agregar la línea:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
al igual que:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
BundleTable.Bundles.RegisterTemplateBundles();
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}
En WebApiConfig.cs , agregue al final de la función Registrar :
// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
Fuente .
En Global.asax estoy usando el código a continuación. Mi URI para obtener JSON eshttp://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"));
}
Eche un vistazo a la negociación de contenido en WebAPI. Estas ( Parte 1 y Parte 2 ) publicaciones de blog maravillosamente detalladas y exhaustivas explican cómo funciona.
En resumen, tiene razón y solo necesita establecer Accept
o Content-Type
solicitar encabezados. Dado que su acción no está codificada para devolver un formato específico, puede establecerla Accept: application/json
.
Como la pregunta es específica de Chrome, puede obtener la extensión Postman que le permite configurar el tipo de contenido de la solicitud.
network.http.accept.default
configuración a 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
para evitar que los hosts con errores como Bitbucket sirvan accidentalmente a su navegador JSON en lugar de HTML.
Una opción rápida es utilizar la especialización MediaTypeMapping. Aquí hay un ejemplo del uso de QueryStringMapping en el evento Application_Start:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a", "b", "application/json"));
Ahora, siempre que la url contenga la cadena de consulta? A = b en este caso, la respuesta de Json se mostrará en el navegador.
Este código hace que json sea mi predeterminado y también me permite usar el formato XML. Solo agregaré el xml=true
.
GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "application/xml"));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
¡Gracias a todos!
No use su navegador para probar su API.
En su lugar, intente utilizar un cliente HTTP que le permita especificar su solicitud, como CURL o incluso Fiddler.
El problema con este problema está en el cliente, no en la API. La API web se comporta correctamente, de acuerdo con la solicitud del navegador.
La mayoría de las respuestas anteriores tiene mucho sentido. Como ve que los datos se formatean en formato XML, eso significa que se aplica el formateador XML, así que puede ver el formato JSON simplemente eliminando el XMLFormatter del parámetro HttpConfiguration como
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();
}
ya que JSON es el formato predeterminado
Utilicé un filtro de acción global para eliminar Accept: application/xml
cuando el User-Agent
encabezado contiene "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();
}
}
Parece funcionar.
La aplicación Chrome "Advanced REST Client" me pareció excelente para trabajar con los servicios REST. Puede establecer el tipo de contenido application/json
entre otras cosas:
cliente REST avanzado
El formateador de tipo medio devuelve el formato correcto. Como otros mencionaron, puedes hacer esto en la WebApiConfig
clase:
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"));
...
}
}
Para más información, consulte:
En caso de que sus acciones devuelvan XML (que es el caso por defecto) y necesita solo un método específico para devolver JSON, puede usar un ActionFilterAttribute
y aplicarlo a esa acción específica.
Atributo de filtro:
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);
}
}
Aplicando a la acción:
[JsonOutput]
public IEnumerable<Person> GetPersons()
{
return _repository.AllPersons(); // the returned output will be in JSON
}
Tenga en cuenta que puede omitir la palabra Attribute
en la decoración de la acción y usar solo en [JsonOutput]
lugar de [JsonOutputAttribute]
.
config.Formatters.Remove(config.Formatters.XmlFormatter);
No me queda claro por qué hay toda esta complejidad en la respuesta. Claro que hay muchas maneras de hacer esto, con QueryStrings, encabezados y opciones ... pero lo que creo que es la mejor práctica es simple. Solicitas una URL simple (ej http://yourstartup.com/api/cars
.:) y a cambio obtienes JSON. Obtiene JSON con el encabezado de respuesta adecuado:
Content-Type: application/json
Al buscar una respuesta a esta misma pregunta, encontré este hilo y tuve que seguir porque esta respuesta aceptada no funciona exactamente. Encontré una respuesta que creo que es demasiado simple para no ser la mejor:
Establecer el formateador predeterminado de WebAPI
Agregaré mi consejo aquí también.
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());
}
Tengo una pregunta de dónde provienen los valores predeterminados (al menos los que estoy viendo). ¿Son valores predeterminados de .NET, o tal vez creados en otro lugar (por alguien más en mi proyecto)? De todos modos, espero que esto ayude.
Aquí hay una solución similar a la de jayson.centeno y otras respuestas, pero usando la extensión integrada de 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
}
La solución se orientó principalmente a admitir el formato $ para OData en las primeras versiones de WebApi, pero también se aplica a la implementación que no es OData y devuelve el
Content-Type: application/json; charset=utf-8
encabezado en la respuesta.
Le permite virar &$format=json
o &$format=xml
al final de su uri cuando prueba con un navegador. No interfiere con otros comportamientos esperados cuando se utiliza un cliente que no es del navegador donde puede configurar sus propios encabezados.
Puedes usar lo siguiente:
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
Simplemente agregue esas dos líneas de código en su clase WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//add this two line
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
............................
}
}
Simplemente cambias App_Start/WebApiConfig.cs
así:
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}"
);
}
Desde MSDN Creación de una aplicación de página única con ASP.NET y AngularJS (aproximadamente 41 minutos).
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();
}
Debería ser actual, lo probé y funcionó.
Ha pasado un tiempo desde que se hizo esta pregunta (y se respondió), pero otra opción es anular el encabezado Aceptar en el servidor durante el procesamiento de la solicitud utilizando un MessageHandler como se muestra a continuación:
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);
}
}
Donde someOtherCondition
puede haber cualquier cosa, incluido el tipo de navegador, etc. Esto sería para casos condicionales donde solo a veces queremos anular la negociación de contenido predeterminada. De lo contrario, según otras respuestas, simplemente eliminaría un formateador innecesario de la configuración.
Deberá registrarlo, por supuesto. Puedes hacer esto globalmente:
public static void Register(HttpConfiguration config) {
config.MessageHandlers.Add(new ForceableContentTypeDelegationHandler());
}
o ruta por ruta:
config.Routes.MapHttpRoute(
name: "SpecialContentRoute",
routeTemplate: "api/someUrlThatNeedsSpecialTreatment/{id}",
defaults: new { controller = "SpecialTreatment" id = RouteParameter.Optional },
constraints: null,
handler: new ForceableContentTypeDelegationHandler()
);
Y dado que este es un manejador de mensajes, se ejecutará tanto en el final de la solicitud como en el de respuesta de forma similar a un HttpModule
. Para que pueda reconocer fácilmente la anulación con un encabezado personalizado:
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;
}
}
Aquí está la forma más fácil que he usado en mis aplicaciones. Agregar a continuación 3 líneas de código App_Start\\WebApiConfig.cs
en Register
función
var formatters = GlobalConfiguration.Configuration.Formatters;
formatters.Remove(formatters.XmlFormatter);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
La API web de Asp.net serializará automáticamente su objeto devuelto a JSON y, a medida que application/json
se agregue en el encabezado, el navegador o el receptor comprenderán que está devolviendo el resultado JSON.
WebApiConfig es el lugar donde puede configurar si desea generar en json o xml. por defecto es xml. en la función de registro podemos usar HttpConfiguration Formatters para formatear la salida. System.Net.Http.Headers => MediaTypeHeaderValue ("text / html") es necesario para obtener la salida en formato json.
Utilizando la respuesta de Felipe Leusin durante años, después de una actualización reciente de las bibliotecas principales y de Json.Net, me encontré con System.MissingMethodException
: SupportedMediaTypes. La solución en mi caso, con suerte útil para otros que experimenten la misma excepción inesperada, es instalar System.Net.Http
. NuGet aparentemente lo elimina en algunas circunstancias. Después de una instalación manual, el problema se resolvió.
Me sorprende ver tantas respuestas que requieren codificación para cambiar un solo caso de uso (GET) en una API en lugar de usar una herramienta adecuada que debe instalarse una vez y puede usarse para cualquier API (propia o de terceros) y todo casos de uso
Entonces la buena respuesta es: