webapi Come faccio a ottenere API Web ASP.NET per restituire JSON anziché XML utilizzando Chrome?




webapi c# json (24)

Ecco il modo più semplice che ho usato nelle mie applicazioni. Aggiungi sotto 3 righe di codice in App_Start\\WebApiConfig.cs nella funzione Register

    var formatters = GlobalConfiguration.Configuration.Formatters;

    formatters.Remove(formatters.XmlFormatter);

    config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));

L'API web Asp.net serializzerà automaticamente l'oggetto restituito su JSON e l' application/json verrà aggiunta nell'intestazione in modo che il browser o il destinatario capiscano che si sta restituendo il risultato JSON.

Utilizzando la più recente API Web ASP.NET , in Chrome vedo XML: come posso modificarlo per richiedere JSON in modo che possa visualizzarlo nel browser? Credo che sia solo una parte delle intestazioni delle richieste, ho ragione in questo?


Aggiungo solo quanto segue nella classe App_Start / WebApiConfig.cs nel mio progetto MVC Web API.

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

Questo fa sì che tu possa ottenere json sulla maggior parte delle query, ma puoi ottenere xml quando invii text/xml .

Se è necessario avere la risposta Content-Type come application/json prega di controllare la risposta di Todd sotto .

NameSpace utilizza System.Net.Http.Headers ;


La maggior parte delle risposte di cui sopra ha perfettamente senso. Dato che stai vedendo i dati formattati in formato XML, significa che viene applicato il formattatore XML, SO puoi vedere il formato JSON rimuovendo semplicemente XMLFormatter dal parametro HttpConfiguration come

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

poiché JSON è il formato predefinito


Sono sbalordito nel vedere tante risposte che richiedono la codifica per modificare un caso di utilizzo singolo (GET) in un'unica API invece di utilizzare uno strumento appropriato che deve essere installato una volta e può essere utilizzato per qualsiasi API (propria o di terze parti) e tutte casi d'uso.

Quindi la buona risposta è:

  1. Se si desidera richiedere solo json o altro tipo di contenuto, installare Requestly o uno strumento simile e modificare l'intestazione Accept.
  2. Se si desidera utilizzare anche il POST e avere json, xml, ecc. Formattati correttamente, utilizzare un'estensione di test API appropriata come Postman o ARC .

Mi piace l'approccio di Felipe Leusin migliore: assicurati che i browser ottengano JSON senza compromettere la negoziazione del contenuto da parte dei client che effettivamente desiderano XML. L'unico elemento mancante per me era che le intestazioni di risposta contenevano ancora il tipo di contenuto: text / html. Perché era un problema? Perché utilizzo l' estensione per Chrome Formatter di Chrome , che controlla il tipo di contenuto, e non ho la bella formattazione a cui sono abituato. Ho risolto questo problema con un semplice formattatore personalizzato che accetta richieste text / html e restituisce le risposte application / 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");
    }
}

Registrati in questo modo:

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

La restituzione del formato corretto viene eseguita dal formattatore del tipo di supporto. Come altri hanno menzionato, puoi farlo nella classe WebApiConfig :

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

        ...
    }
}

Per ulteriori informazioni, controlla:

Nel caso in cui le tue azioni restituiscano XML (che è il caso per impostazione predefinita) e hai bisogno solo di un metodo specifico per restituire JSON, puoi quindi utilizzare ActionFilterAttribute e applicarlo a quell'azione specifica.

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

Applicando all'azione:

[JsonOutput]
public IEnumerable<Person> GetPersons()
{
    return _repository.AllPersons(); // the returned output will be in JSON
}

Si noti che è possibile omettere la parola Attribute sulla decorazione dell'azione e utilizzare solo [JsonOutput] invece di [JsonOutputAttribute] .


Non mi è chiaro il motivo per cui c'è tutta questa complessità nella risposta. Certo, ci sono molti modi per farlo, con QueryStrings, intestazioni e opzioni ... ma quello che ritengo sia la migliore pratica è semplice. Si richiede un URL semplice (es: http://yourstartup.com/api/cars ) e in cambio si ottiene JSON. Ottieni JSON con l'intestazione di risposta appropriata:

Content-Type: application/json

Cercando una risposta a questa stessa domanda, ho trovato questo thread e ho dovuto continuare perché questa risposta accettata non funziona esattamente. Ho trovato una risposta che ritengo sia troppo semplice per non essere la migliore:

Imposta il formattatore WebAPI predefinito

Aggiungerò anche il mio consiglio qui.

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

Ho una domanda su dove vengono i valori predefiniti (almeno quelli che vedo). Sono predefiniti .NET, o forse creati da qualche altra parte (da qualcun altro sul mio progetto). Anways, spero che questo aiuti.


Ecco una soluzione simile a jayson.centeno's e altre risposte, ma utilizzando l'estensione incorporata da 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 soluzione era principalmente orientata a supportare il formato $ per OData nelle prime versioni di WebApi, ma si applica anche all'implementazione non OData e restituisce Content-Type: application/json; charset=utf-8 Content-Type: application/json; charset=utf-8 intestazione nella risposta.

Ti consente di aggiungere &$format=json o &$format=xml alla fine del tuo uri durante il test con un browser. Non interferisce con gli altri comportamenti previsti quando si utilizza un client non browser in cui è possibile impostare le proprie intestazioni.


Usando la risposta di Felipe Leusin per anni, dopo un recente aggiornamento delle librerie di base e di Json.Net, mi sono imbattuto in un System.MissingMethodException : SupportedMediaTypes. La soluzione nel mio caso, si spera utile per gli altri che stanno vivendo la stessa eccezione inaspettata, è quella di installare System.Net.Http . Apparentemente NuGet lo rimuove in alcune circostanze. Dopo un'installazione manuale, il problema è stato risolto.


Questo codice rende json my default e mi permette di usare anche il formato XML. Aggiungerò semplicemente xml=true .

GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "application/xml"));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

Grazie a tutti!


Puoi usare come di seguito:

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

WebApiConfig è il posto in cui è possibile configurare se si desidera eseguire l'output in json o xml. di default è xml. nella funzione di registro possiamo usare HttpConfiguration Formatters per formattare l'output. System.Net.Http.Headers => MediaTypeHeaderValue ("text / html") è richiesto per ottenere l'output nel formato json.


Se lo fai in WebApiConfig otterrai JSON per impostazione predefinita, ma ti consentirà comunque di restituire XML se passi text/xml come richiesta Accept intestazione

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

Se non si utilizza il tipo di progetto MVC e quindi non si dispone di questa classe per iniziare, vedere questa risposta per i dettagli su come incorporarlo.


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

Basta aggiungere quelle due linee di codice sulla tua classe WebApiConfig

public static class WebApiConfig
{
     public static void Register(HttpConfiguration config)
     {
          //add this two line 
          config.Formatters.Clear();
          config.Formatters.Add(new JsonMediaTypeFormatter());


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

Devi semplicemente modificare App_Start/WebApiConfig.cs questo modo:

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

MVC4 Suggerimento rapido n. 3: rimozione del formattatore XML dall'API Web ASP.Net

In Global.asax aggiungi la riga:

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

così:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    BundleTable.Bundles.RegisterTemplateBundles();
    GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}

Dai un'occhiata alla negoziazione del contenuto in WebAPI. Questi post del blog dettagliati e dettagliati ( Parte 1 e Parte 2 ) spiegano come funziona.

In breve, hai ragione e devi solo impostare le intestazioni di richiesta Accept o Content-Type . Dato che la tua azione non è codificata per restituire un formato specifico, puoi impostare Accept: application/json .


Ho usato un filtro di azione globale per rimuovere Accept: application/xml quando l'intestazione 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();
    }
}

Sembra funzionare.


È trascorso un po 'di tempo da quando questa domanda è stata posta (e risposta), ma un'altra opzione è quella di sovrascrivere l'intestazione Accept sul server durante l'elaborazione della richiesta utilizzando un MessageHandler come di seguito:

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

Dove someOtherCondition può essere qualsiasi cosa, incluso il tipo di browser, ecc. Questo sarebbe per i casi condizionali in cui solo a volte vogliamo sovrascrivere la negoziazione del contenuto predefinita. In caso contrario, come per le altre risposte, sarà sufficiente rimuovere un formattatore non necessario dalla configurazione.

Dovrai registrarti, ovviamente. Puoi farlo a livello globale:

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

o su una rotta per base:

config.Routes.MapHttpRoute(
   name: "SpecialContentRoute",
   routeTemplate: "api/someUrlThatNeedsSpecialTreatment/{id}",
   defaults: new { controller = "SpecialTreatment" id = RouteParameter.Optional },
   constraints: null,
   handler: new ForceableContentTypeDelegationHandler()
);

E poiché questo è un gestore di messaggi, verrà eseguito sia sulla richiesta che sulla risposta della pipeline, proprio come un HttpModule . Quindi potresti facilmente riconoscere l'override con un'intestazione personalizzata:

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

Da MSDN Creazione di un'applicazione a pagina singola con ASP.NET e AngularJS (circa 41 minuti in).

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

Dovrebbe essere attuale, l'ho provato e ha funzionato.


Ho trovato l'app Chrome "Advanced REST Client" eccellente per lavorare con i servizi REST. È possibile impostare Content-Type su application/json tra le altre cose: Advanced REST client


Un'opzione rapida è usare la specializzazione MediaTypeMapping. Ecco un esempio di utilizzo di QueryStringMapping nell'evento Application_Start:

GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a", "b", "application/json"));

Ora ogni volta che l'url contiene querystring? A = b in questo caso, la risposta Json verrà mostrata nel browser.


Poiché la domanda è specifica per Chrome, puoi ottenere l' estensione Postman che ti consente di impostare il tipo di contenuto della richiesta.





asp.net-web-api