¿Cómo consigo que ASP.NET Web API devuelva JSON en lugar de XML usando Chrome?

1220

Al usar 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 la solicitud, ¿estoy en lo cierto?

1
1797

Nota: lea los comentarios de esta respuesta, puede producir una vulnerabilidad XSS si está utilizando el manejo de errores predeterminado de WebAPI

Acabo de agregar lo siguiente en App_Start / WebApiConfig.csclase en mi proyecto de API web MVC .

config.Formatters.JsonFormatter.SupportedMediaTypes
    .Add(new MediaTypeHeaderValue("text/html") );

Eso asegura que obtenga JSON en la mayoría de las consultas, pero puede obtenerlo XMLcuando envíe text/xml.

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

NameSpaceestá usando System.Net.Http.Headers.

23
  • 118
    Esta es una respuesta sorprendentemente pasada por alto, y aunque la pregunta original no estaba totalmente clara, esto convierte directamente a JSON en la respuesta predeterminada para un navegador web (que envía Aceptar: texto / html). Buen trabajo.
    gregmac
    15 de enero de 2013 a las 1:44
  • 17
    +1 De lejos la mejor respuesta. Me imagino que hay un montón de personas que optan por eliminar completamente XML solo porque no ven JSON en el navegador. 16/11/2013 a las 9:51
  • 3
    Cuando hice esto, descubrí que los datos proporcionados por un tercero con etiquetas de rotura HTML terminaban con retornos de carro. Entonces, el JSON no era válido. Es mejor usar la respuesta aceptada si esto te afecta. 14 de marzo de 2014 a las 15:03
  • 24
    Tenga en cuenta que el Content-Typeencabezado de la respuesta seguirá siendo text/html.
    Mrchief
    2 de mayo de 2014 a las 17:29
  • 83
    Esto es horrible. El encabezado del tipo de contenido de respuesta debe ser application / json. Esta "solución" lo convierte en texto / html. 10/07/2014 a las 21:01
509

Si hace esto en el WebApiConfig, obtendrá JSON de forma predeterminada, pero aún le permitirá devolver XML si lo pasa text/xmlcomo el Acceptencabezado de la solicitud .

Nota: Esto elimina el soporte para 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);
    }
}

Si no está utilizando el tipo de proyecto MVC y, por lo tanto, no tenía esta clase para empezar, consulte esta respuesta para obtener detalles sobre cómo incorporarla.

7
  • 51
    Solo para notar, el comportamiento original es correcto. Solicitudes de Chrome application/xmlcon una prioridad de 0.9 y */*con 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.
    porges
    26/0313 a las 21:20
  • 12
    ¿Soy yo o la primera oración es incorrecta? El código parece eliminar completamente XML, no simplemente cambiar el predeterminado.
    NickG
    9/04/2013 a las 18:24
  • 6
    @NickG: una solución que se pasa por alto aquí y en mi humilde opinión es una opción mucho mejor (mantener la aplicación / xml) es la solución propuesta por Felipe Leusin más abajo en esta página. Usando config.Formatters.XmlFormatter.SupportedMediaTypes.Add (new MediaTypeHeaderValue ("texto / html"));
    Cohen
    3 de julio de 2013 a las 10:10
  • 1
    Entonces, ¿cómo lo hacemos a través de la configuración web para obtener json de forma predeterminada y XML si se solicita?
    Kyle
    3 de septiembre de 2013 a las 1:40
  • 4
    La respuesta de @Felipse Leusin a continuación es en realidad más corta y funciona mejor. 9 de septiembre de 2013 a las 13:20
334

El uso de RequestHeaderMapping funciona aún mejor, porque también establece el Content-Type = application/jsonencabezado de 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"));
11
  • 7
    Esta es la solución más sencilla y sencilla y Fiddler también detecta el tipo de contenido que se devuelve como josn. 7 mar.15 a las 21:06
  • 4
    ¡Bonito! ¿Dónde sugeriría poner esto en el código? 22 de mayo de 2015 a las 2:40
  • 10
    Debería ir en WebApiConfig.cs
    Animesh
    25 de junio de 2015 a las 8:11
  • 9
    Trabajó para mi. Necesitaba agregar un uso de System.Net.Http.Formatting; 9 de febrero de 2016 a las 10:03
  • 1
    Vinculación para mi propia conveniencia: esta respuesta funciona bien con otro paso de configuración que suelo realizar: stackoverflow.com/a/28337589/398630 . 5 de mayo de 2017 a las 16:03
320

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 quieren XML. La única pieza que me faltaba era que los encabezados de respuesta todavía contenían content-type: text / html. ¿Por qué fue eso un problema? Porque utilizo la extensión JSON Formatter Chrome , que inspecciona el tipo de contenido, y no obtengo el formato bonito al que estoy acostumbrado. Lo solucioné 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());
11
  • 24
    En el constructor, agregue this.SerializerSettings.Formatting = Formatting.Indented;si lo desea con una impresión bonita sin una extensión de navegador. 15 de mayo de 2014 a las 14:48
  • 11
    ¿Por qué querrías que se imprimiera bastante sobre el cable? 10 de julio de 2014 a las 21:04
  • 8
    ¿No es la respuesta de @ dmit77 mejor (más concisa) que esta? 1 dic '14 a las 12:00
  • 8
    @eddiegroves, no quieres una impresión bonita sobre el cable. Desea que el servidor envíe la menor cantidad de bits a través del cable (es decir, sin espacios). Entonces desea que el navegador lo formatee bien, con complementos y demás. Javascript necesita analizar el JSON por lo general, ¿por qué hacerlo más lento al introducir un formato innecesario? 12 feb.15 a las 20:53
  • 13
    Para los googlers que buscan: no olvides agregar using System.Net.Http.Formattingyusing Newtonsoft.Json
    Berriel
    16 de septiembre de 2015 a las 1:46
189

Consejo rápido n.º 3 de MVC4: eliminación del formateador XML de la API web ASP.Net

En Global.asaxagregue 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();
}
6
  • 9
    Funciona: mucho mejor si JSON es el predeterminado en lugar de XML. 15/04/12 a las 22:38
  • 5
    pero ¿puedes devolver xml entonces? 4 de julio de 12 a las 0:37
  • 100
    Lo probé y no puedes. Así que esto está eliminando la compatibilidad con XML. Tengan cuidado, queridos usuarios de Google. 4 de julio de 12 a las 0:42
  • 3
    Si echa un vistazo a mi respuesta a continuación, esto permitirá que xml se devuelva si lo desea, pero permite que el sitio responda con JSON al navegador 24 de septiembre de 2012 a las 1:17
  • 3
    @GlennSlaven, sí, tu respuesta debería ser la marcada como la correcta. 14/10/12 a las 16:46
119

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

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

Fuente .

6
  • 1
    En MVC5, esto se puede hacer reemplazando config con GlobalConfiguration.
    Steven
    19 de septiembre de 2013 a las 13:50
  • 5
    Para un proyecto que debe ser compatible solo con JSON y bajo ninguna circunstancia se puede permitir que emita XML, esta es, con mucho, la mejor opción.
    Luc C
    15 de julio de 2014 a las 12:45
  • 1
    config.Formatters.Add (config.Formatters.JsonFormatter); 16/04/15 a las 13:41
  • 3
    Eso es terrible. - Esto siempre devolverá JSON pase lo que pase, incluso si el cliente solicita específicamente XML en el encabezado Content-Type. 5 de mayo de 2017 a las 21:30
  • 1
    Los proyectos que no prueben la versión XML de la API tan a fondo como su versión JSON deben optar por esto. Los objetos se serializan de manera diferente por los diferentes formateadores según el enlace que Michael incluyó. Por ejemplo: los formateadores XML no serializan campos de solo lectura, mientras que el formateador JSON sí. 5 de noviembre de 2020 a las 4:42
98

En Global.asax estoy usando el siguiente código. 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"));
}
1
54

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

En resumen, tiene razón y solo necesita establecer los encabezados de solicitud Accepto Content-Type. Dado que su acción no está codificada para devolver un formato específico, puede establecer Accept: application/json.

2
  • 6
    "para que pueda verlo en el navegador" 5/0313 a las 19:19
  • 1
    @Spongman, sí puedes. Pero use una extensión como REST Client; la mayoría de los navegadores tienen una similar. La escritura directa de URL en un navegador es 1. Demasiado limitante (no hay control sobre los encabezados, no se pueden publicar datos, etc.); 2. Incorrecto: el navegador no consume la API web como se pretende que se consuma; no puede confiar en que la pruebe correctamente. Entonces, nuevamente, un buen complemento de cliente REST solucionaría eso. 25/04/2014 a las 21:37
44

Como la pregunta es específica de Chrome, puede obtener la extensión Postman que le permite establecer el tipo de contenido de la solicitud.

Cartero

3
  • En Firefox, simplemente vaya a about: config, busque accept.default y cambie el contenido de la network.http.accept.defaultconfiguración a text/html,application/xhtml+xml,application/json;q=0.9,application/xml;q=0.8,*/*;q=0.7. 6 de junio de 2018 a las 10:48
  • O mejor aún, solo text/html,application/xhtml+xml;q=1.0,*/*;q=0.7para evitar que hosts con errores como Bitbucket sirvan accidentalmente JSON de su navegador en lugar de HTML. 6/06/18 a las 11:01
  • La URL está muerta. Uno nuevo es chrome.google.com/webstore/detail/postman/… . 2 de julio de 2018 a las 4:34
35

Una opción rápida es utilizar la especialización MediaTypeMapping. A continuación, se muestra 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.

1
  • 2
    Esto fue muy útil. También puede usar UriPathExtensionMapping en lugar de QueryStringMapping si desea usar path.to/item.json 13/04/12 a las 23:28
34

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!

2
  • 1
    Esta es la respuesta más flexible (y realmente debería ser la configuración predeterminada en estos días). Para agregar a esta respuesta, JSON es el predeterminado, incluso desde el navegador. Para ver XML, agregue la cadena de consulta:? Xml = true 30 de marzo de 2014 a las 14:04
  • Probé varias estrategias. Tuve una prueba simple tanto para XML como para JSON y esto funcionó de inmediato 17/06/15 a las 21:55
21

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, según la solicitud del navegador.

3
  • 32
    ¿Por qué no utilizar el navegador? Es una herramienta obvia para ello. 18 de septiembre de 2012 a las 6:37
  • 5
    Creo que el punto aquí es correcto e importante: no debemos corregir una parte funcional de la aplicación (la infraestructura MVC WebAPI) si el problema es causado por el cliente. El caso de uso real de una API es que se use correctamente (proporcionando encabezados correctos), que es responsabilidad de la aplicación. Sin embargo, no estoy de acuerdo con descartar completamente el navegador; para probar, hay muchas herramientas para casi cualquier navegador (para empezar, extensiones similares a Rest Client). 25/04/2014 a las 21:30
  • 8
    Probablemente debería ser un comentario.
    bonh
    14 de mayo de 2015 a las 19:14
18

La mayoría de las respuestas anteriores tiene mucho sentido. Dado que está viendo que los datos se formatean 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

0
11

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

11

El formateador de tipo de medio realiza la devolución del formato correcto. Como otros mencionaron, puede hacer esto en la WebApiConfigclase:

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 obtener más información, consulte:

En caso de que sus acciones devuelvan XML (que es el caso de forma predeterminada) y solo necesita un método específico para devolver JSON, puede usar un ActionFilterAttributey 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);
    }
}

Aplicar 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 Attributeen la decoración de la acción y usar solo en [JsonOutput]lugar de [JsonOutputAttribute].

10

Encontré la aplicación de Chrome "Advanced REST Client" excelente para trabajar con servicios REST. Puede establecer el tipo de contenido application/jsonentre otras cosas: cliente REST avanzado

8

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

debajo WebApiConfig.cs, esto funcionará

config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
8
        config.Formatters.Remove(config.Formatters.XmlFormatter);
1
  • 3
    Si bien este código puede responder a la pregunta, proporcionar un contexto adicional sobre cómo y / o por qué resuelve el problema mejoraría el valor de la respuesta a largo plazo. Lea este stackoverflow.com/help/how-to-answer
    S.R
    1 de julio de 2017 a las 4:52
6

No me queda claro por qué hay toda esta complejidad en la respuesta. Seguro que hay muchas formas de hacer esto, 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/carsy, 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 continuar porque esta respuesta aceptada no funciona exactamente. Encontré una respuesta que creo que es demasiado simple para no ser la mejor:

Establecer el formateador WebAPI predeterminado

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 los valores predeterminados de .NET o quizás los creó en otro lugar (por otra persona en mi proyecto)? De todos modos, espero que esto ayude.

6

Puede utilizar de la siguiente manera:

GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
1
  • Si está creando una aplicación WebAPI para simplemente pasar mensajes JSON, considere esta respuesta.
    allen1
    31/12/18 a las 20:35
5

Aquí hay una solución similar a la de jayson.centeno y otras respuestas, pero usando la extensión incorporada 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 estaba orientada 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 de OData y devuelve el Content-Type: application/json; charset=utf-8encabezado en la respuesta.

Le permite virar &$format=jsono &$format=xmlal final de su uri cuando lo prueba con un navegador. No interfiere con otros comportamientos esperados cuando se utiliza un cliente que no es un navegador en el que puede configurar sus propios encabezados.

5

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


          ............................
      }
}
3

Simplemente cambia App_Start/WebApiConfig.csasí:

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}"
       );
    }
2
  • Eliminar un formateador generalmente no es una buena idea, está eliminando funcionalidad. 8 de febrero de 2016 a las 15:36
  • De hecho, en este caso, a mí me funciona bien, también muchos otros sugieren una forma como esta. ¡Lo aprendí del libro myview.rahulnivi.net/building-spa-angular-mvc-5 !
    vaheeds
    8 de febrero de 2016 a las 19:03
2

Desde MSDN Creación de una aplicación de página única con ASP.NET y AngularJS (aproximadamente 41 minutos en).

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 estar actualizado, lo probé y funcionó.

0
2

Ha pasado algún tiempo desde que se hizo (y se respondió) esta pregunta, pero otra opción es anular el encabezado Accept en el servidor durante el procesamiento de la solicitud usando 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 someOtherConditionpuede 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.

Deberá registrarlo, por supuesto. Puede 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 controlador de mensajes, se ejecutará tanto en los extremos de solicitud como de respuesta de la canalización de manera muy similar a un archivo HttpModule. Por lo tanto, podría 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;
    }
}
2

Esta es la forma más sencilla que he utilizado en mis aplicaciones. Agregue las siguientes 3 líneas de código App_Start\\WebApiConfig.csen Registerfunció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/jsonse agregue en el encabezado, el navegador o el receptor comprenderán que está devolviendo el resultado JSON.

1

Usando la respuesta de Felipe Leusin durante años, después de una actualización reciente de las bibliotecas centrales y de Json.Net, me encontré con System.MissingMethodException: SupportedMediaTypes. La solución en mi caso, con suerte útil para otros que experimentan 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ó.

1

WebApiConfig es el lugar donde puede configurar si desea generar en json o xml. De forma predeterminada, 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.

ingrese la descripción de la imagen aquí

-3

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 que debe instalarse una vez y puede usarse para cualquier API (propia o de terceros) y todas casos de uso.

Entonces 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 Accept.
  2. Si también desea usar POST y tiene json, xml, etc. bien formateados, use una extensión de prueba de API adecuada como Postman o ARC .
3
  • Algunos prefieren hacer cosas sin agregar hinchazón en forma de herramientas y bibliotecas adicionales.
    tno2007
    24 feb.20 a las 16:15
  • Sigue siendo incorrecto realizar cambios en la API solo porque alguien está utilizando la herramienta incorrecta para el trabajo. Un navegador web no está diseñado para probar API, ni siquiera para ver el resultado de las API, sino para ver documentos. Es incluso peor si alguien piensa que una herramienta de prueba de API es abultada en lugar de ser parte del kit de herramientas obligatorio para cualquier desarrollador de API, y honestamente, también agregaría desarrolladores frontales porque también necesitan interactuar y experimentar con API. Probablemente tampoco sea suficiente porque el navegador sin complementos no permite establecer encabezados, publicar en una API o incluso inspeccionar encabezados de respuesta. 24 feb.20 a las 20:51
  • Entiendo lo que dices y no te equivocas. Pero fuera de tema, la razón por la que se le rechaza es el tono en el que responde la pregunta. Suenas muy combativo y te pareces a ese desarrollador que cree que lo sabe todo, y eso es muy desagradable. Estoy seguro de que es un gran desarrollador, a juzgar por sus respuestas. Pero, debe aprender, especialmente en un entorno de control de calidad profesional como este, a dirigirse y convencer a las personas de una manera más amigable y humana. Quizás, primero dé la respuesta que quieren, luego explique una mejor manera y motive por qué es mejor.
    tno2007
    25 feb.20 a las 0:18