google-chrome return - ¿Cómo obtengo la API web de ASP.NET para devolver JSON en lugar de XML utilizando Chrome?




example c# (25)

Según la última versión de ASP.net WebApi 2,

bajo WebApiConfig.cs , esto funcionará

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

Al usar la nueva API web de ASP.NET , en Chrome , estoy viendo XML. ¿Cómo puedo cambiarlo para solicitar JSON y poder verlo en el navegador? Creo que es solo una parte de los encabezados de solicitud, ¿estoy en lo correcto?


Se puede utilizar de la siguiente manera:

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

Simplemente cambia el App_Start/WebApiConfig.cs esta manera:

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

Ha pasado algo de 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 ser cualquier cosa, incluido el tipo de navegador, etc. Esto sería para casos condicionales en los que 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.

Tendrás que registrarte por supuesto. Usted puede hacer esto globalmente:

  public static void Register(HttpConfiguration config) {
      config.MessageHandlers.Add(new ForceableContentTypeDelegationHandler());
  }

o en una 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 se trata de un controlador de mensajes, se ejecutará en los extremos de solicitud y respuesta de la canalización de manera muy similar a un HttpModule . Por lo tanto, puede 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;
    }
}

Desde MSDN Creación de una aplicación de una sola página 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ó.


La aplicación Chrome "Advanced REST Client" me pareció excelente para trabajar con los servicios REST. Puede configurar Content-Type para application/json entre otras cosas: Cliente REST avanzado


En el WebApiConfig.cs , agregue al final de la función de registro :

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

Source


Si hace esto en el WebApiConfig obtendrá JSON de forma predeterminada, pero aún así le permitirá devolver XML si pasa text/xml como el encabezado Accept 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, vea esta respuesta para obtener detalles sobre cómo incorporarlo.


WebApiConfig es el lugar donde puede configurar si desea imprimir en json o xml. por defecto es xml. en la función de registro podemos usar los formateadores de configuración de Http para formatear la salida. Se requiere System.Net.Http.Headers => MediaTypeHeaderValue ("text / html") para obtener la salida en el formato json.


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


          ............................
      }
}

El uso de RequestHeaderMapping funciona incluso mejor, porque también establece Content-Type = application/json en el encabezado de respuesta, lo que permite a Firefox (con el complemento JSONView) formatear la respuesta como JSON.

GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings
.Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept", 
                              "text/html",
                              StringComparison.InvariantCultureIgnoreCase,
                              true, 
                              "application/json"));

La mayoría de las respuestas anteriores tienen perfecto sentido. Dado que los datos se están formateando en formato XML, eso significa que se aplica el formateador XML, de modo que puede ver el formato JSON simplemente eliminando 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


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. La única pieza que faltaba para mí era que los encabezados de respuesta aún 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 consigo el formato bonito al que estoy acostumbrado. Lo solucioné con un sencillo formateador personalizado 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");
    }
}

Registrarse como tal:

config.Formatters.Add(new BrowserJsonFormatter());

Una opción rápida es utilizar la especialización MediaTypeMapping. Este es 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.


Esta es la forma más fácil que he usado en mis aplicaciones. Agregue las siguientes 3 líneas de código en App_Start\\WebApiConfig.cs en la función de Register

    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, al agregarse la application/json en el encabezado, el navegador o el receptor entenderán que está devolviendo el resultado JSON.


Echa un vistazo a la negociación de contenido en la WebAPI. Estas ( Parte 1 y Parte 2 ) maravillosamente detalladas y detalladas publicaciones en el blog explican cómo funciona.

En resumen, tiene razón y solo necesita configurar los encabezados de solicitud de Accept o Content-Type . Dado que su Acción no está codificada para devolver un formato específico, puede configurar 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.


No me queda claro por qué hay toda esta complejidad en la respuesta. Seguro que hay muchas formas de hacerlo, con QueryStrings, encabezados y opciones ... pero lo que creo que es la mejor práctica es simple. Solicita una URL simple (por ejemplo, http://yourstartup.com/api/cars ) y a cambio obtiene JSON. Obtienes 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 adelante 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

Voy a añadir 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 los valores predeterminados de .NET, o tal vez creados en otro lugar (por alguien más en mi proyecto)? En fin, espero que esto ayude.


Acabo de agregar lo siguiente en la clase App_Start / WebApiConfig.cs 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 obtener xml cuando envía text/xml .

Si necesita tener la respuesta Content-Type como application/json , verifique la respuesta de Todd a continuación .

NameSpace está utilizando System.Net.Http.Headers ;


Me sorprende ver tantas respuestas que requieren codificación para cambiar un caso de uso único (GET) en una API en lugar de usar una herramienta adecuada, lo que debe instalarse una vez y se puede usar para cualquier API (propia o de terceros) y todo casos de uso.

Así que la buena respuesta es:

  1. Si solo desea solicitar json u otro tipo de contenido, instale Requestly o una herramienta similar y modifique el encabezado Aceptar.
  2. Si desea utilizar POST también y tiene un formato agradable json, xml, etc., use una extensión de prueba de API adecuada como Postman o ARC .

MVC4 Sugerencia rápida nº 3: eliminar el formateador XML de la API web de ASP.Net

En Global.asax agrega 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();
}

        config.Formatters.Remove(config.Formatters.XmlFormatter);

Usé un filtro de acción global para eliminar Accept: application/xml cuando el encabezado User-Agent 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.


No uses tu navegador para probar tu 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.


A partir de Chrome 48+, puede acceder a la vista previa de impresión a través de los siguientes pasos:

  1. Abra las herramientas de desarrollo - Ctrl / Cmd + Shift + I o haga clic derecho en la página y seleccione 'Inspeccionar'.

  2. Pulsa Esc para abrir el cajón adicional.

  3. Si 'Rendering' no se está mostrando, haga clic en el kebab de 3 puntos y seleccione 'rendering'.

  4. Marque la casilla de verificación 'Emular medios impresos'.

Desde allí, Chrome le mostrará una versión impresa de su página y podrá inspeccionar elementos y solucionar problemas como si fuera la versión del navegador.





json google-chrome asp.net-web-api