Bei Verwendung der neueren ASP.NET-Web-API wird in Chrome XML angezeigt. Wie kann ich es ändern, um JSON anzufordern, damit ich es im Browser anzeigen kann? Ich glaube, es ist nur ein Teil der Anforderungsheader. Stimmt das?
Bei Verwendung der neueren ASP.NET-Web-API wird in Chrome XML angezeigt. Wie kann ich es ändern, um JSON anzufordern, damit ich es im Browser anzeigen kann? Ich glaube, es ist nur ein Teil der Anforderungsheader. Stimmt das?
Antworten:
Ich füge App_Start / WebApiConfig.cs
in meinem MVC- Web-API- Projekt nur Folgendes in der Klasse hinzu .
config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("text/html") );
Das stellt sicher, dass Sie JSON für die meisten Abfragen erhalten, aber Sie können es erhalten, XML
wenn Sie senden text/xml
.
Wenn Sie die Antwort haben müssen , Content-Type
wie application/json
überprüfen Sie bitte Todd Antwort unten .
NameSpace
verwendet System.Net.Http.Headers
.
Content-Type
Header der Antwort weiterhin angezeigt wird text/html
.
Wenn Sie diese in das tun WebApiConfig
werden Sie JSON standardmäßig, aber es wird immer noch ermöglichen es Ihnen , XML zurück , wenn Sie passieren text/xml
als Accept
Anforderungskopf
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 zunächst nicht hatten, finden Sie in dieser Antwort Einzelheiten zur Einbindung.
application/xml
mit einer Priorität von 0,9 und */*
einer Priorität von 0,8. Durch Entfernen application/xml
entfernen Sie die Möglichkeit für die Web-API, XML zurückzugeben, wenn der Client dies ausdrücklich anfordert. Wenn Sie beispielsweise "Accept: application / xml" senden, erhalten Sie weiterhin JSON.
Die Verwendung von RequestHeaderMapping funktioniert noch besser, da auch der Content-Type = application/json
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"));
Ich mag den Ansatz von Felipe Leusin am besten - stellen Sie sicher, dass Browser JSON erhalten, ohne die Inhaltsverhandlung von Clients zu beeinträchtigen, die tatsächlich XML möchten. Das einzige fehlende Teil für mich war, dass die Antwortheader immer noch den Inhaltstyp enthielten: text / html. Warum war das ein Problem? Weil ich die JSON Formatter Chrome-Erweiterung verwende , die den Inhaltstyp überprüft, und 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());
this.SerializerSettings.Formatting = Formatting.Indented;
Sie im Konstruktor hinzu, wenn Sie möchten, dass es ohne Browsererweiterung hübsch gedruckt wird.
using System.Net.Http.Formatting
undusing Newtonsoft.Json
MVC4-Kurztipp 3 - Entfernen des XML-Formatierers aus der ASP.Net-Web-API
In Global.asax
die Zeile:
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();
}
Fügen Sie in der Datei WebApiConfig.cs am Ende der Registerfunktion Folgendes hinzu :
// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
Quelle .
In der Global.asax verwende ich den folgenden Code. Meine URI, um JSON zu erhalten, isthttp://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"));
}
Schauen Sie sich die Inhaltsverhandlung in der 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 Accept
oder Content-Type
Anforderungsheader festlegen. Da Ihre Aktion nicht für die Rückgabe eines bestimmten Formats codiert ist, können Sie festlegen Accept: application/json
.
Da die Frage Chrome-spezifisch ist, können Sie die Postman-Erweiterung erhalten , mit der Sie den Inhaltstyp der Anforderung festlegen können.
network.http.accept.default
Konfiguration in text/html,application/xhtml+xml,application/json;q=0.9,application/xml;q=0.8,*/*;q=0.7
.
text/html,application/xhtml+xml;q=1.0,*/*;q=0.7
zu vermeiden, dass fehlerhafte Hosts wie Bitbucket versehentlich Ihren Browser-JSON anstelle von HTML bedienen.
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"));
Immer wenn die URL in diesem Fall den Querystring? A = b enthält, wird die Json-Antwort im Browser angezeigt.
Dieser Code macht json zu meiner Standardeinstellung und ermöglicht mir auch die Verwendung des XML-Formats. Ich werde nur die anhängen xml=true
.
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!
Verwenden Sie Ihren Browser nicht zum Testen Ihrer API.
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.
Die meisten der oben genannten Antworten sind absolut sinnvoll. Da Daten im XML-Format formatiert werden, 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
Ich habe einen globalen Aktionsfilter verwendet, um zu entfernen, Accept: application/xml
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.
Ich fand die Chrome-App "Advanced REST Client" hervorragend für die Arbeit mit REST-Diensten. Sie können den Inhaltstyp application/json
unter anderem auf Folgendes einstellen :
Erweiterter REST-Client
Die Rückgabe des richtigen Formats erfolgt durch den Medientyp-Formatierer. Wie bereits erwähnt, können Sie dies in der WebApiConfig
Klasse 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 eine verwenden 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);
}
}
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
auf der Aktionsdekoration weglassen und [JsonOutput]
stattdessen anstelle von verwenden können [JsonOutputAttribute]
.
config.Formatters.Remove(config.Formatters.XmlFormatter);
Mir ist unklar, warum die Antwort all diese Komplexität enthält. Sicher, es gibt viele Möglichkeiten, wie Sie dies mit QueryStrings, Headern und Optionen tun können ... 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 fand ich diesen Thread und musste weitermachen, da diese akzeptierte Antwort nicht genau funktioniert. Ich habe eine Antwort gefunden, die meiner Meinung nach einfach zu einfach ist, um nicht die beste zu sein:
Legen Sie den Standard-WebAPI-Formatierer fest
Ich werde auch hier 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 (zumindest die, die ich sehe) stammen. Sind sie .NET-Standardeinstellungen oder wurden sie möglicherweise woanders erstellt (von jemand anderem in meinem Projekt)? Ich hoffe, das hilft.
Hier ist eine Lösung ähnlich der von jayson.centeno und anderen Antworten, jedoch 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 in erster Linie auf die Unterstützung des $ -Formats für OData in den frühen Versionen von WebApi ausgerichtet, gilt jedoch auch für die Nicht-OData-Implementierung und gibt den
Content-Type: application/json; charset=utf-8
Header in der Antwort zurück.
Es ermöglicht Ihnen, beim Testen mit einem Browser zu heften &$format=json
oder &$format=xml
bis zum Ende Ihres Uri. Es beeinträchtigt nicht das andere erwartete Verhalten, wenn Sie einen Nicht-Browser-Client verwenden, in dem Sie Ihre eigenen Header festlegen können.
Sie können wie folgt verwenden:
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
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());
............................
}
}
Sie ändern einfach Folgendes App_Start/WebApiConfig.cs
:
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}"
);
}
Von MSDN Erstellen einer Einzelseitenanwendung mit ASP.NET und AngularJS (ca. 41 Minuten).
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.
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 mithilfe eines MessageHandlers 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);
}
}
Wo someOtherCondition
kann etwas sein, einschließlich Browsertyp usw. Dies wäre für bedingte Fälle, in denen wir nur manchmal die Standardaushandlung von Inhalten überschreiben möchten. Andernfalls würden Sie gemäß anderen Antworten 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 für Route Basis:
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 Nachrichtenhandler ist, wird er sowohl am Anforderungs- als auch am Antwortende der Pipeline ausgeführt, ähnlich wie bei einem 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;
}
}
Hier ist der einfachste Weg, den ich in meinen Anwendungen verwendet habe. Fügen Sie die unten angegebenen 3 Codezeilen App_Start\\WebApiConfig.cs
in die Register
Funktion 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 in JSON und wenn das application/json
im Header hinzugefügt wird, wird der Browser oder der Empfänger verstehen, dass Sie das JSON-Ergebnis zurückgeben.
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 Formatters verwenden, um die Ausgabe zu formatieren. System.Net.Http.Headers => MediaTypeHeaderValue ("text / html") ist erforderlich, um die Ausgabe im json-Format abzurufen.
Mit Felipe Leusin ‚s Antwort jahrelang nach einer letzten Aktualisierung der Kernbibliotheken und von Json.Net, lief ich in ein System.MissingMethodException
: SupportedMediaTypes. Die Lösung in meinem Fall, die hoffentlich für andere hilfreich ist, bei denen dieselbe unerwartete Ausnahme auftritt, ist die Installation System.Net.Http
. NuGet entfernt es anscheinend unter bestimmten Umständen. Nach einer manuellen Installation wurde das Problem behoben.
Ich bin erstaunt zu sehen, dass so viele Antworten eine 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: