¿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?

Borek Bernard
fuente
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"));
    }
}
Dmitry Pavlov
fuente
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().

Filip W
fuente
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());
        }
    }
}
JJ_Coder4Hire
fuente
9
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

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

Bat_Programmer
fuente
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));
    }
}
Luke Puplett
fuente
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();
Durilka
fuente
Si desea algo para un método, solo cree un msdn.microsoft.com/en-us/library/…
Elisabeth
2

Esto tiene los encabezados correctos establecidos. Parece un poco más elegante.

public JsonResult<string> TestMethod() 
{
return Json("your string or object");
}
Netferret
fuente
1
¿Cuáles son los nombres completos de las clases JsonResult y Json?
Josh Withee
0

Puede usar en WebApiConfig.cs:

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
Antonio
fuente
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());

            [...]
        }
Carlo Saccone
fuente