it-swarm.com.de

Wie kann ich erreichen, dass die ASP.NET-Web-API mithilfe von Chrome JSON anstelle von XML zurückgibt?

Mit der neueren ASP.NET Web API in Chrome sehe ich XML - wie kann ich es ändern, um JSON anzufordern, damit ich kann im Browser anzeigen? Ich glaube, es ist nur ein Teil der Anforderungsheader, bin ich richtig?

1220
naspinski

In meinem MVC-Web-API-Projekt füge ich in der Klasse App_Start / WebApiConfig.cs Folgendes hinzu.

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

Das stellt sicher, dass Sie bei den meisten Abfragen JSON erhalten, aber Sie können xml erhalten, wenn Sie text/xml senden.

Wenn Sie die Antwort Content-Type als application/json benötigen, überprüfen Sie bitte Todd's Antwort unten .

NameSpace verwendet System.Net.Http.Headers;

1668
Felipe Leusin

Wenn Sie dies in der WebApiConfig tun, erhalten Sie standardmäßig JSON, können aber trotzdem XML zurückgeben, wenn Sie text/xml als Anforderungsheader Accept übergeben

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

Wenn Sie den MVC-Projekttyp nicht verwenden und diese Klasse daher nicht zu Beginn hatten, siehe diese Antwort für Einzelheiten zur Einbindung.

494
Glenn Slaven

Ich mag Felipe Leusins ​​Ansatz am besten - stelle sicher, dass Browser JSON erhalten, ohne die Inhaltsaushandlung von Clients zu beeinträchtigen, die tatsächlich XML wollen. Das einzige fehlende Teil für mich war, dass die Antwort-Header immer noch den Inhaltstyp "text/html" enthielten. Warum war das ein Problem? Weil ich die JSON Formatter Chrome -Erweiterung verwende, die den Inhaltstyp überprüft, und ich nicht die hübsche Formatierung bekomme, die ich gewohnt bin. Ich habe das mit einem einfachen benutzerdefinierten Formatierer behoben, der Text-/HTML-Anforderungen akzeptiert und Anwendungs-/JSON-Antworten zurückgibt:

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

Registrieren Sie sich wie folgt:

config.Formatters.Add(new BrowserJsonFormatter());
300
Todd Menier

Die Verwendung von RequestHeaderMapping funktioniert sogar noch besser, da der Content-Type = application/json im Antwortheader festgelegt wird, sodass Firefox (mit JSONView-Add-On) die Antwort als JSON formatieren kann.

GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings
.Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept", 
                              "text/html",
                              StringComparison.InvariantCultureIgnoreCase,
                              true, 
                              "application/json"));
287
dmit77

MVC4 Quick Tip Nr. 3 - Entfernen des XML-Formatierers von der ASP.Net-Web-API

Fügen Sie in Global.asax die folgende Zeile hinzu:

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

wie so:

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

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

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

Fügen Sie in der Datei WebApiConfig.cs am Ende der Funktion Register hinzu :

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

Quelle .

109

In der Global.asax verwende ich den folgenden Code. Mein URI für JSON ist http://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"));
}
91
Diganta Kumar

Schauen Sie sich die Inhaltsverhandlung im WebAPI an. Diese ( Teil 1 & Teil 2 ) wunderbar detaillierten und gründlichen Blog-Beiträge erklären, wie es funktioniert.

Kurz gesagt, Sie haben Recht und müssen nur die Anforderungsheader Accept oder Content-Type setzen. Da Ihre Aktion nicht so programmiert ist, dass sie ein bestimmtes Format zurückgibt, können Sie Accept: application/json einstellen.

53
Aaron Daniels

Da die Frage Chrome-spezifisch ist, können Sie die Postman-Erweiterung erhalten, mit der Sie den Anforderungsinhaltstyp festlegen können.

Postman

43
Chris S

Eine schnelle Option ist die Verwendung der MediaTypeMapping-Spezialisierung. Hier ist ein Beispiel für die Verwendung von QueryStringMapping im Application_Start-Ereignis:

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

Wenn die URL in diesem Fall den Querystring? A = b enthält, wird die Json-Antwort im Browser angezeigt.

34
suhair

Dieser Code macht json zu meinem Standard und ermöglicht mir, auch das XML-Format zu verwenden. Ich werde einfach den xml=true anhängen.

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

Vielen Dank an alle!

30
jayson.centeno

Verwenden Sie nicht Ihren Browser, um Ihre API zu testen.

Versuchen Sie stattdessen, einen HTTP-Client zu verwenden, mit dem Sie Ihre Anforderung angeben können, z. B. CURL oder sogar Fiddler.

Das Problem mit diesem Problem liegt im Client, nicht in der API. Die Web-API verhält sich gemäß der Anforderung des Browsers korrekt.

20
dmyoko

Die meisten der oben genannten Antworten sind absolut sinnvoll. Da Sie sehen, dass Daten im XML-Format formatiert sind, bedeutet dies, dass der XML-Formatierer angewendet wird. Sie können also das JSON-Format anzeigen, indem Sie den XMLFormatter wie folgt aus dem Parameter HttpConfiguration entfernen

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

da JSON das Standardformat ist

15
pavan kumar

Ich habe einen globalen Aktionsfilter verwendet, um Accept: application/xml zu entfernen, wenn der User-Agent -Header "Chrome" enthält:

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

Scheint zu funktionieren.

10
Roger Lipscombe

Ich fand die Chrome App "Advanced REST Client" hervorragend für die Arbeit mit REST Services. Sie können den Content-Type unter anderem auf application/json setzen: Advanced REST client

9
Mike Rowley

Die Rückgabe des richtigen Formats erfolgt durch den Medientyp-Formatierer. Wie bereits erwähnt, können Sie dies in der Klasse WebApiConfig tun:

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

        ...
    }
}

Weitere Informationen finden Sie unter:

Wenn Ihre Aktionen XML zurückgeben (was standardmäßig der Fall ist) und Sie nur eine bestimmte Methode benötigen, um JSON zurückzugeben, können Sie ein ActionFilterAttribute verwenden und es auf diese bestimmte Aktion anwenden.

Filterattribut:

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

Auf die Aktion anwenden:

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

Beachten Sie, dass Sie das Wort Attribute in der Aktionsdekoration weglassen und nur [JsonOutput] anstelle von [JsonOutputAttribute] verwenden können.

7
Stacked

Mir ist nicht klar, warum die Antwort so komplex ist. Sicher, es gibt viele Möglichkeiten, dies mit QueryStrings, Headern und Optionen zu tun, aber was ich für die beste Vorgehensweise halte, ist einfach. Sie fordern eine einfache URL an (z. B. http://yourstartup.com/api/cars) und erhalten dafür JSON. Sie erhalten JSON mit dem richtigen Antwortheader:

Content-Type: application/json

Auf der Suche nach einer Antwort auf dieselbe Frage habe ich diesen Thread gefunden und musste weitermachen, da diese akzeptierte Antwort nicht genau funktioniert. Ich habe eine Antwort gefunden, die ich für zu einfach halte, um nicht die beste zu sein:

Legen Sie den Standard-WebAPI-Formatierer fest

Ich werde hier auch meinen Tipp hinzufügen.

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

Ich habe eine Frage, woher die Standardeinstellungen stammen (zumindest die, die ich sehe). Handelt es sich um .NET-Standardeinstellungen, oder handelt es sich um etwas, das an einer anderen Stelle erstellt wurde (von jemand anderem in meinem Projekt)? Ich hoffe immer, das hilft.

5
Nick

gemäß der neuesten Version von ASP.net WebApi 2,

unter WebApiConfig.cs wird dies funktionieren

config.Formatters.Remove(GlobalConfiguration.Configuration.Formatters.XmlFormatter);
config.Formatters.Add(GlobalConfiguration.Configuration.Formatters.JsonFormatter);
4
A.T.

Hier ist eine Lösung, die jayson.centeno's und anderen Antworten ähnlich ist, aber die eingebaute Erweiterung von System.Net.Http.Formatting verwendet.

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
 }

Die Lösung war in erster Linie auf die Unterstützung des Formats $ für OData in früheren Versionen von WebApi ausgerichtet. Sie gilt jedoch auch für die Nicht-OData-Implementierung und gibt den Header Content-Type: application/json; charset=utf-8 in der Antwort zurück.

Es ermöglicht Ihnen, &$format=json oder &$format=xml beim Testen mit einem Browser bis zum Ende Ihrer URL anzuheften. Wenn Sie einen Nicht-Browser-Client verwenden, in dem Sie Ihre eigenen Header festlegen können, beeinträchtigt dies nicht das erwartete Verhalten.

4
mdisibio
        config.Formatters.Remove(config.Formatters.XmlFormatter);
3
Gaurav Dubey

Sie können wie folgt verwenden:

GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
3
Akshay Kapoor

Fügen Sie einfach diese beiden Codezeilen in Ihre Klasse WebApiConfig ein

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


          ............................
      }
}
2

Sie ändern einfach den App_Start/WebApiConfig.cs wie folgt:

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
vaheeds

From MSDNErstellen einer Einzelseitenanwendung mit ASP.NET und AngularJS (ungefähr 41 Minuten 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();
    }

Es sollte aktuell sein, ich habe es versucht und es hat funktioniert.

1
lko

Es ist einige Zeit vergangen, seit diese Frage gestellt (und beantwortet) wurde. Eine andere Möglichkeit besteht darin, den Accept-Header auf dem Server während der Anforderungsverarbeitung mit einem MessageHandler wie folgt zu überschreiben:

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

Wobei someOtherCondition alles sein kann, einschließlich des Browsertyps usw. Dies gilt für bedingte Fälle, in denen nur gelegentlich die standardmäßige Inhaltsaushandlung außer Kraft gesetzt werden soll. Andernfalls würden Sie, wie in den anderen Antworten angegeben, einfach einen unnötigen Formatierer aus der Konfiguration entfernen.

Sie müssen es natürlich registrieren. Sie können dies entweder global tun:

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

oder auf einer Route auf Routenbasis:

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

Und da dies ein Message-Handler ist, wird er sowohl am Anforderungs- als auch am Antwortende der Pipeline ausgeführt, ähnlich wie ein HttpModule. So können Sie die Überschreibung leicht mit einem benutzerdefinierten Header bestätigen:

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

Hier ist der einfachste Weg, den ich in meinen Anwendungen verwendet habe. Fügen Sie die folgenden 3 Codezeilen in die Funktion App_Start\\WebApiConfig.cs in Register ein

    var formatters = GlobalConfiguration.Configuration.Formatters;

    formatters.Remove(formatters.XmlFormatter);

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

Die Asp.net-Web-API serialisiert Ihr zurückgegebenes Objekt automatisch zu JSON und fügt application/json in die Kopfzeile ein, damit der Browser oder der Empfänger versteht, dass Sie das JSON-Ergebnis zurückgeben.

1
Vikas Bansal

Nachdem ich die Antwort von Felipe Leusin jahrelang nach einem kürzlichen Update der Kernbibliotheken und von Json.Net verwendet hatte, stieß ich auf System.MissingMethodException: SupportedMediaTypes. In meinem Fall besteht die Lösung, die hoffentlich auch für andere hilfreich ist, darin, System.Net.Http zu installieren. NuGet entfernt es anscheinend unter bestimmten Umständen. Nach einer manuellen Installation wurde das Problem behoben.

0
Charles Burns

In WebApiConfig können Sie konfigurieren, ob Sie in json oder xml ausgeben möchten. standardmäßig ist es xml. In der Registerfunktion können wir HttpConfiguration-Formatierer verwenden, um die Ausgabe zu formatieren. System.Net.Http.Headers => MediaTypeHeaderValue ("text/html") ist erforderlich, um die Ausgabe im json-Format zu erhalten. enter image description here

0
rocky_pps