Jak zmusić interfejs API sieci Web ASP.NET, aby zawsze zwracał kod JSON?

103

ASP.NET Web API domyślnie negocjuje zawartość - zwróci XML, JSON lub inny typ na podstawie Acceptnagłówka. Nie potrzebuję / nie chcę tego, czy istnieje sposób (na przykład atrybut lub coś), aby powiedzieć interfejsowi API sieci Web, aby zawsze zwracał JSON?

Borek Bernard
źródło
Możesz to zrobić, usuwając wszystkie elementy formatujące z wyjątkiem json zGlobalConfiguration.Configuration.Formatters
Claudio Redi

Odpowiedzi:

75

Obsługa tylko formatu JSON w ASP.NET Web API - WŁAŚCIWY SPOSÓB

Zamień IContentNegotiator na JsonContentNegotiator:

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

Implementacja 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
źródło
4
gdzie pierwsza część kodu również jest wycinana i wklejana? Nie widzę obiektu „config” w moim Global.asax. Skąd pochodzi ta zmienna? artykuł również nie wyjaśnia.
BuddyJoe
3
Sprawdź metodę public static void Register (HttpConfiguration config) {...} w pliku WebApiConfig.cs, która została oceniona przez VS2012 podczas tworzenia projektu
Dmitry Pavlov
Czy to wymusi JSON w tym sensie, że klient AcceptXML otrzyma JSON, a nie 406 ?
Luke Puplett
1
Potrafię odpowiedzieć na swój komentarz / pytanie: zwraca XML niezależnie od Acceptnagłówka.
Luke Puplett
2
To psuje moją integrację swashbuckle i wydaje się, że jest to związane z tym problemem na github ( github.com/domaindrivendev/Swashbuckle/issues/219 ). Chciałbym użyć tej metody, ale ta poniżej GlobalConfiguration...Clear()faktycznie działa.
seangwright
167

Wyczyść wszystkie elementy formatujące i dodaj ponownie program formatujący Json.

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

EDYTOWAĆ

Dodałem to do Global.asaxśrodka Application_Start().

Filip W.
źródło
iw którym pliku .. ?? global.ascx .. ??
shashwat
W metodzie Application_Start ()
Jafin
6
Filip W właśnie stał się lepszy :), zobacz tutaj strathweb.com/2013/06/…
Tien Do
7
@TienDo - link do własnego bloga Filipa?
Phill
10

Philip W miał właściwą odpowiedź, ale dla jasności i kompletnego działającego rozwiązania, edytuj plik Global.asax.cs tak, aby wyglądał następująco: (Zauważ, że musiałem dodać referencję System.Net.Http.Formatting do pliku wygenerowanego w magazynie)

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
źródło
9
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

Spowoduje to wyczyszczenie programu formatującego XML, a tym samym ustawienie domyślnego formatu JSON.

Bat_Programmer
źródło
Idealne wszystko, co jest potrzebne
tfa
4

Zainspirowany doskonałą odpowiedzią Dmitrija Pawłowa, nieznacznie ją zmieniłem, aby móc podłączyć dowolny formatyzator, którego chciałem wymusić.

Kredyt dla Dmitrija.

/// <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
źródło
2

Jeśli chcesz to zrobić tylko dla jednej metody, zadeklaruj swoją metodę jako zwracającą HttpResponseMessagezamiast IEnumerable<Whatever>i wykonaj:

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

ten kod jest trudny do testowania jednostkowego, ale jest to również możliwe w następujący sposób:

    sut = new WhateverController() { Configuration = new HttpConfiguration() };
    sut.Configuration.Formatters.Add(new Mock<JsonMediaTypeFormatter>().Object);
    sut.Request = new HttpRequestMessage();
durilka
źródło
Jeśli chcesz coś dla metody, utwórz tylko msdn.microsoft.com/en-us/library/…
Elisabeth
2

To ma ustawione poprawne nagłówki. Wydaje się nieco bardziej elegancki.

public JsonResult<string> TestMethod() 
{
return Json("your string or object");
}
Netferret
źródło
1
Jakie są w pełni kwalifikowane nazwy klas JsonResult i Json?
Josh Withee
0

Możesz użyć w WebApiConfig.cs:

config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
Antonio
źródło
0

dla osób używających OWIN

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

staje się (w Startup.cs):

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

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

            [...]
        }
Carlo Saccone
źródło