¿Cómo forzar a ASP.NET Web API a devolver siempre JSON?


103

ASP.NET Web API realiza la negociación de contenido de forma predeterminada: devolverá XML o JSON u otro tipo según el Acceptencabezado. No necesito / quiero esto, ¿hay alguna manera (como un atributo o algo así) de decirle a la API web que siempre devuelva JSON?


Es posible que pueda hacer esto eliminando todos los formateadores excepto json deGlobalConfiguration.Configuration.Formatters
— Claudio Redi

Respuestas:


75

Compatible solo con JSON en ASP.NET Web API: EL CAMINO CORRECTO

Reemplace IContentNegotiator con JsonContentNegotiator:

var jsonFormatter = new JsonMediaTypeFormatter();
//optional: set serializer settings here
config.Services.Replace(typeof(IContentNegotiator), new JsonContentNegotiator(jsonFormatter));

Implementación de JsonContentNegotiator:

public class JsonContentNegotiator : IContentNegotiator
{
    private readonly JsonMediaTypeFormatter _jsonFormatter;

    public JsonContentNegotiator(JsonMediaTypeFormatter formatter) 
    {
        _jsonFormatter = formatter;    
    }

    public ContentNegotiationResult Negotiate(
            Type type, 
            HttpRequestMessage request, 
            IEnumerable<MediaTypeFormatter> formatters)
    {
        return new ContentNegotiationResult(
            _jsonFormatter, 
            new MediaTypeHeaderValue("application/json"));
    }
}

4
¿Dónde se corta y pega la primera parte del código también? No veo un objeto "config" en mi Global.asax. ¿De dónde viene esa variable? el artículo tampoco explica.
— BuddyJoe

3
Verifique el método {...} public static void Register (HttpConfiguration config) en el archivo WebApiConfig.cs que ha sido generado por VS2012 en la creación del proyecto
— Dmitry Pavlov

¿Forzará esto JSON en el sentido de que un AcceptXML cliente obtendrá JSON y no un 406 ?
— Luke Puplett

1
Puedo responder mi propio comentario / pregunta: devuelve XML cualquiera que sea el Acceptencabezado.
— Luke Puplett

2
Esto rompe mi integración de capa y espada y parece que está relacionado con este problema en github ( github.com/domaindrivendev/Swashbuckle/issues/219 ). Me gustaría usar este método, pero el que se muestra a continuación GlobalConfiguration...Clear()realmente funciona.
— seangwright

167

Borre todos los formateadores y vuelva a agregar el formateador Json.

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

EDITAR

Lo agregué al Global.asaxinterior Application_Start().


y en que archivo .. ?? global.ascx .. ??
— shashwat

En su método Application_Start ()
— Jafin

6
Filip W acaba de mejorar ahora :), véalo
— Tien Do

7
@TienDo: ¿vincular al propio blog de Filip?
— Phill

10

Philip W tenía la respuesta correcta, pero para mayor claridad y una solución de trabajo completa, edite su archivo Global.asax.cs para que se vea así: (Tenga en cuenta que tuve que agregar la referencia System.Net.Http.Formatting al archivo generado en stock)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http.Formatting;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;

namespace BoomInteractive.TrainerCentral.Server {
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801

    public class WebApiApplication : System.Web.HttpApplication {
        protected void Application_Start() {
            AreaRegistration.RegisterAllAreas();

            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            //Force JSON responses on all requests
            GlobalConfiguration.Configuration.Formatters.Clear();
            GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
        }
    }
}

9
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

Esto borra el formateador XML y, por lo tanto, el formato JSON es el predeterminado.


Perfeccione todo lo que se necesita
— tfa

4

Inspirado por la excelente respuesta de Dmitry Pavlov, la modifiqué ligeramente para poder conectar cualquier formateador que quisiera aplicar.

Crédito a Dmitry.

/// <summary>
/// A ContentNegotiator implementation that does not negotiate. Inspired by the film Taken.
/// </summary>
internal sealed class LiamNeesonContentNegotiator : IContentNegotiator
{
    private readonly MediaTypeFormatter _formatter;
    private readonly string _mimeTypeId;

    public LiamNeesonContentNegotiator(MediaTypeFormatter formatter, string mimeTypeId)
    {
        if (formatter == null)
            throw new ArgumentNullException("formatter");

        if (String.IsNullOrWhiteSpace(mimeTypeId))
            throw new ArgumentException("Mime type identifier string is null or whitespace.");

        _formatter = formatter;
        _mimeTypeId = mimeTypeId.Trim();
    }

    public ContentNegotiationResult Negotiate(Type type, HttpRequestMessage request, IEnumerable<MediaTypeFormatter> formatters)
    {
        return new ContentNegotiationResult(_formatter, new MediaTypeHeaderValue(_mimeTypeId));
    }
}

2

Si desea hacer eso solo para un método, declare su método como regresando en HttpResponseMessagelugar de IEnumerable<Whatever>y haga:

    public HttpResponseMessage GetAllWhatever()
    {
        return Request.CreateResponse(HttpStatusCode.OK, new List<Whatever>(), Configuration.Formatters.JsonFormatter);
    }

este código es doloroso para las pruebas unitarias, pero también es posible así:

    sut = new WhateverController() { Configuration = new HttpConfiguration() };
    sut.Configuration.Formatters.Add(new Mock<JsonMediaTypeFormatter>().Object);
    sut.Request = new HttpRequestMessage();

Si desea algo para un método, solo cree un msdn.microsoft.com/en-us/library/…
— Elisabeth


0

Puede usar en WebApiConfig.cs:

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

0

para aquellos que usan OWIN

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

se convierte en (en Startup.cs):

   public void Configuration(IAppBuilder app)
        {
            OwinConfiguration = new HttpConfiguration();
            ConfigureOAuth(app);

            OwinConfiguration.Formatters.Clear();
            OwinConfiguration.Formatters.Add(new DynamicJsonMediaTypeFormatter());

            [...]
        }
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.