tutorial - json mediatypeformatter web api




Wie kann ich die ASP.NET-Web-API dazu bringen, JSON anstelle von XML mithilfe von Chrome zurückzugeben? (20)

Wenn ich die neuere ASP.NET-Web-API verwende , sehe ich in Chrome XML - wie kann ich es ändern, um JSON anzufordern, damit ich es im Browser anzeigen kann? Ich glaube, es ist nur ein Teil der Anfrage Header, bin ich richtig darin?


Da die Frage Chrome-spezifisch ist, können Sie die Postman-Erweiterung abrufen , mit der Sie den Inhaltstyp der Anfrage festlegen können.


Die Rückgabe des korrekten Formats erfolgt über den Formatierer des Medientyps. 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"));

        ...
    }
}

Für mehr, überprüfen Sie:

Wenn Ihre Aktionen XML zurückgeben (was standardmäßig der Fall ist) und Sie nur eine bestimmte Methode zum Zurückgeben von JSON benötigen, können Sie ein ActionFilterAttribute und 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);
    }
}

Anwendung auf Aktion:

[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] .


Die meisten der oben genannten Antworten sind durchaus sinnvoll. Da Sie sehen, dass Daten im XML-Format formatiert werden, bedeutet dies, dass XML-Formatierung angewendet wird. Daher können Sie das JSON-Format nur durch Entfernen des XMLFormatter aus dem HttpConfiguration-Parameter sehen

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

seit JSON ist das Standardformat


Dieser Code macht Json zu meinem Standard und erlaubt mir, auch das XML-Format zu verwenden. Ich füge einfach das xml=true .

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

Danke allen!


Es ist einige Zeit vergangen, seit diese Frage gestellt (und beantwortet) wurde, aber eine andere Option besteht darin, den Accept-Header auf dem Server während der Anfrageverarbeitung 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 Browser-Typ usw. Dies wäre für bedingte Fälle, in denen wir nur gelegentlich die Standard-Inhaltsverhandlung außer Kraft setzen wollen. Anderenfalls würden Sie 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 Route für Route:

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 auf der HttpModule auf der Antwort-Seite der Pipeline ähnlich wie ein HttpModule . So können Sie die Überschreibung mit einem benutzerdefinierten Header leicht 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;
    }
}

Es ist mir unklar, warum all diese Komplexität in der Antwort steckt. Sicher, es gibt viele Möglichkeiten, wie Sie dies tun können, mit QueryStrings, Kopfzeilen und Optionen ... aber was ich für die beste Praxis halte, ist einfach. Sie fordern eine einfache URL an (zB 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 genau diese Frage fand ich diesen Thread und musste weitermachen, weil diese akzeptierte Antwort nicht genau funktioniert. Ich habe eine Antwort gefunden, die ich einfach zu einfach finde, um nicht die beste zu sein:

Legen Sie das Standard-WebAPI-Formatierungsprogramm fest

Ich werde meinen Tipp hier auch 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, wo die Standardeinstellungen (zumindest die, die ich sehe) herkommen. Sind sie .NET-Standardeinstellungen oder wurden sie an anderer Stelle (von jemand anderem in meinem Projekt) erstellt? Anways, hoffe das hilft.


Hier ist eine ähnliche Lösung wie jayson.centeno's und andere Antworten, aber mit der integrierten Erweiterung von 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
 }

Die Lösung war hauptsächlich auf die Unterstützung des $ -Formats für OData in den frühen Versionen von WebApi ausgerichtet, gilt aber auch für die Nicht-OData-Implementierung und gibt den Content-Type: application/json; charset=utf-8 Content-Type: application/json; charset=utf-8 Header in der Antwort.

Es ermöglicht Ihnen, &$format=json oder &$format=xml am Ende Ihrer URL anzubringen, wenn Sie mit einem Browser testen. Es beeinträchtigt nicht das andere erwartete Verhalten, wenn Sie einen Client ohne Browser verwenden, in dem Sie eigene Header festlegen können.


Ich bin erstaunt, so viele Antworten zu sehen, die Codierung erfordern, um einen einzelnen Anwendungsfall (GET) in einer API zu ändern, anstatt ein geeignetes Tool zu verwenden, das einmal installiert werden muss und für jede API (eigene oder Drittanbieter) und alle verwendet werden kann Anwendungsfälle.

Die gute Antwort lautet also:

  1. Wenn Sie nur json oder einen anderen Inhaltstyp Requestly möchten, installieren Sie Requestly oder ein ähnliches Tool und ändern Sie den Accept-Header.
  2. Wenn Sie POST auch verwenden und schön formatierte json, xml, etc. verwenden möchten, verwenden Sie eine richtige API-Test-Erweiterung wie Postman oder ARC .

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 arbeiten.


Ich mag den Ansatz von Felipe Leusin am besten - stellen Sie sicher, dass Browser JSON erhalten, ohne die Inhaltsverhandlung von Clients zu gefährden, die eigentlich XML wollen. Das einzige fehlende Stück für mich war, dass die Response-Header immer noch content-type enthalten: text / html. Warum war das ein Problem? Weil ich die JSON Formatter Chrome-Erweiterung verwende , die den Inhaltstyp prüft, und ich bekomme nicht die hübsche Formatierung, die ich gewohnt bin. Ich habe das mit einem einfachen benutzerdefinierten Formatierer korrigiert, der Text / HTML-Anfragen 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 so:

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

MVC4 Quick Tipp # 3 - Entfernen der XML-Formatierung von ASP.Net Web API

In Global.asax fügen Sie die Zeile hinzu:

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

so:

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

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

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

Sehen Sie sich die Inhaltsverhandlung in der WebAPI an. Diese ( Teil 1 & Teil 2 ) wunderbar detaillierten und gründlichen Blogbeiträge erklären, wie es funktioniert.

Kurz gesagt, Sie haben Recht und müssen nur die Anforderungsheader " Accept oder " Content-Type festlegen. Wenn Ihre Aktion nicht für die Rückgabe eines bestimmten Formats codiert ist, können Sie Accept: application/json festlegen.


Sie können wie folgt verwenden:

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

Verwenden Sie Ihren Browser nicht, 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 und nicht in der API. Die Web-API verhält sich entsprechend der Anfrage des Browsers korrekt.


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


Wenn Sie dies in der WebApiConfig tun, WebApiConfig Sie standardmäßig JSON, aber Sie können weiterhin XML zurückgeben, wenn Sie text/xml als Request Accept header ü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 daher nicht über diese Klasse verfügen, finden Sie in dieser Antwort weitere Informationen zur Einbindung.


Fügen Sie in dem WebApiConfig.cs an dem Ende der Register- Funktion hinzu:

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

Source .


Fügen Sie einfach diese beiden Codezeilen zu Ihrer WebApiConfig- Klasse hinzu

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


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

Ich füge einfach in App_Start / WebApiConfig.cs Klasse in meinem MVC Web API-Projekt 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 wenn Sie text/xml senden.

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

NameSpace verwendet System.Net.Http.Headers ;


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




asp.net-web-api