Korzystając z nowszego interfejsu API sieci Web ASP.NET , w przeglądarce Chrome widzę XML - jak mogę go zmienić, aby żądał JSON, aby wyświetlać go w przeglądarce? Wierzę, że to tylko część nagłówków żądania, czy mam rację?
Korzystając z nowszego interfejsu API sieci Web ASP.NET , w przeglądarce Chrome widzę XML - jak mogę go zmienić, aby żądał JSON, aby wyświetlać go w przeglądarce? Wierzę, że to tylko część nagłówków żądania, czy mam rację?
Odpowiedzi:
Właśnie dodałem następujące elementy w App_Start / WebApiConfig.cs
klasie w moim projekcie MVC Web API .
config.Formatters.JsonFormatter.SupportedMediaTypes
.Add(new MediaTypeHeaderValue("text/html") );
Dzięki temu otrzymujesz JSON na większość zapytań, ale możesz je otrzymać XML
po wysłaniu text/xml
.
Jeśli musisz mieć odpowiedź Content-Type
jak application/json
należy sprawdzić odpowiedź Todda poniżej .
NameSpace
używa System.Net.Http.Headers
.
Content-Type
nagłówek odpowiedzi nadal będzie text/html
.
Jeśli zrobisz to w WebApiConfig
, domyślnie otrzymasz JSON, ale nadal pozwoli ci zwrócić XML, jeśli podasz text/xml
jako Accept
nagłówek żądania
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);
}
}
Jeśli nie używasz typu projektu MVC i dlatego nie miałeś tej klasy na początek, zapoznaj się z tą odpowiedzią, aby uzyskać szczegółowe informacje na temat jego włączenia.
application/xml
z priorytetem 0,9 i */*
priorytetem 0,8. Usuwając application/xml
usuwasz możliwość zwracania XML przez interfejs API sieci Web, jeśli klient tego zażąda. np. jeśli wyślesz „Akceptuj: aplikacja / xml”, nadal otrzymasz JSON.
Korzystanie z RequestHeaderMapping działa jeszcze lepiej, ponieważ ustawia również Content-Type = application/json
w nagłówku odpowiedzi, co pozwala Firefoksowi (z dodatkiem JSONView) sformatować odpowiedź jako JSON.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings
.Add(new System.Net.Http.Formatting.RequestHeaderMapping("Accept",
"text/html",
StringComparison.InvariantCultureIgnoreCase,
true,
"application/json"));
Najbardziej podoba mi się podejście Felipe Leusin - upewnij się, że przeglądarki otrzymują JSON bez narażania negocjacji treści od klientów, którzy faktycznie chcą XML. Jedynym brakującym elementem było dla mnie to, że nagłówki odpowiedzi nadal zawierały content-type: text / html. Dlaczego to był problem? Ponieważ używam rozszerzenia JSON Formatter Chrome , które sprawdza typ zawartości i nie otrzymuję ładnego formatowania, do którego jestem przyzwyczajony. Naprawiłem to za pomocą prostego niestandardowego formatera, który przyjmuje żądania tekstowe / HTML i zwraca odpowiedzi aplikacji / 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");
}
}
Zarejestruj się tak:
config.Formatters.Add(new BrowserJsonFormatter());
this.SerializerSettings.Formatting = Formatting.Indented;
jeśli chcesz, aby był ładnie wydrukowany bez rozszerzenia przeglądarki.
using System.Net.Http.Formatting
iusing Newtonsoft.Json
Szybka porada MVC4 # 3 - Usuwanie formatera XML z ASP.Net Web API
W Global.asax
dodać linię:
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
tak:
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
BundleTable.Bundles.RegisterTemplateBundles();
GlobalConfiguration.Configuration.Formatters.XmlFormatter.SupportedMediaTypes.Clear();
}
W pliku WebApiConfig.cs dodaj na końcu funkcji rejestru :
// Remove the XML formatter
config.Formatters.Remove(config.Formatters.XmlFormatter);
Źródło .
W Global.asax używam poniższego kodu. Mój identyfikator URI, aby uzyskać JSON, tohttp://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"));
}
Zobacz negocjacje zawartości w interfejsie WebAPI. Te ( część 1 i część 2 ) niezwykle szczegółowe i dokładne posty na blogu wyjaśniają, jak to działa.
Krótko mówiąc, masz rację i wystarczy ustawić nagłówki Accept
lub Content-Type
żądanie. Ponieważ akcja nie jest zakodowana w celu zwrócenia określonego formatu, możesz ustawić Accept: application/json
.
Ponieważ pytanie dotyczy Chrome, możesz uzyskać rozszerzenie Postman, które pozwala ustawić typ zawartości żądania.
network.http.accept.default
konfiguracji na 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
aby uniknąć błędnych hostów, takich jak Bitbucket, przed przypadkowym udostępnieniem przeglądarki JSON zamiast HTML.
Jedną szybką opcją jest skorzystanie ze specjalizacji MediaTypeMapping. Oto przykład użycia QueryStringMapping w zdarzeniu Application_Start:
GlobalConfiguration.Configuration.Formatters.JsonFormatter.MediaTypeMappings.Add(new QueryStringMapping("a", "b", "application/json"));
Teraz, gdy adres URL zawiera w tym przypadku kwerendę? A = b, odpowiedź Jsona będzie wyświetlana w przeglądarce.
Ten kod sprawia, że Json jest moim domyślnym i pozwala mi również używać formatu XML. Po prostu dołączę xml=true
.
GlobalConfiguration.Configuration.Formatters.XmlFormatter.MediaTypeMappings.Add(new QueryStringMapping("xml", "true", "application/xml"));
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
Dziękuję wszystkim!
Nie używaj przeglądarki do testowania interfejsu API.
Zamiast tego spróbuj użyć klienta HTTP, który pozwala określić żądanie, takie jak CURL, a nawet Fiddler.
Problem z tym problemem leży w kliencie, a nie w interfejsie API. Internetowy interfejs API działa poprawnie, zgodnie z żądaniem przeglądarki.
Większość powyższych odpowiedzi ma sens. Ponieważ widzisz dane formatowane w formacie XML, oznacza to, że zastosowano formatator XML, więc możesz zobaczyć format JSON po prostu usuwając XMLFormatter z parametru HttpConfiguration, takiego jak
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();
}
ponieważ JSON jest formatem domyślnym
Użyłem globalnego filtra akcji, aby usunąć, Accept: application/xml
gdy User-Agent
nagłówek zawiera „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();
}
}
Wydaje się, że działa.
Uważam, że aplikacja Chrome „Advanced REST Client” doskonale nadaje się do współpracy z usługami REST. Możesz ustawić Content-Type na application/json
między innymi:
Zaawansowany klient REST
Prawidłowy format jest zwracany przez formatyzator typu media. Jak wspomnieli inni, możesz to zrobić w WebApiConfig
klasie:
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"));
...
}
}
Aby uzyskać więcej, sprawdź:
W przypadku, gdy twoje działania zwracają XML (co jest domyślnym przypadkiem) i potrzebujesz tylko określonej metody, aby zwrócić JSON, możesz następnie użyć ActionFilterAttribute
i zastosować ją do tej konkretnej akcji.
Filtruj atrybut:
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);
}
}
Zastosowanie do działania:
[JsonOutput]
public IEnumerable<Person> GetPersons()
{
return _repository.AllPersons(); // the returned output will be in JSON
}
Pamiętaj, że możesz pominąć słowo Attribute
na dekoracji akcji i użyć go [JsonOutput]
zamiast [JsonOutputAttribute]
.
config.Formatters.Remove(config.Formatters.XmlFormatter);
Nie jest dla mnie jasne, dlaczego w odpowiedzi jest cała ta złożoność. Oczywiście istnieje wiele sposobów, aby to zrobić, dzięki QueryStrings, nagłówkom i opcjom ... ale to, co uważam za najlepszą praktykę, jest proste. Żądasz prostego adresu URL (np http://yourstartup.com/api/cars
.:), aw zamian dostajesz JSON. Otrzymasz JSON z odpowiednim nagłówkiem odpowiedzi:
Content-Type: application/json
Szukając odpowiedzi na to samo pytanie, znalazłem ten wątek i musiałem kontynuować, ponieważ ta zaakceptowana odpowiedź nie działa dokładnie. Znalazłem odpowiedź, która moim zdaniem jest zbyt prosta, aby nie być najlepszą:
Ustaw domyślny formatyzator WebAPI
Dodam tutaj również moją wskazówkę.
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());
}
Mam pytanie, skąd biorą się wartości domyślne (przynajmniej te, które widzę). Czy są to ustawienia domyślne .NET, czy może zostały utworzone gdzieś indziej (przez kogoś innego z mojego projektu). Zawsze mam nadzieję, że to pomoże.
Oto rozwiązanie podobne do odpowiedzi jayson.centeno i innych, ale przy użyciu wbudowanego rozszerzenia z 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
}
Rozwiązanie było ukierunkowane przede wszystkim na obsługę formatu $ dla OData we wczesnych wersjach WebApi, ale dotyczy również implementacji innej niż OData i zwraca
Content-Type: application/json; charset=utf-8
nagłówek w odpowiedzi.
To pozwala na sczepienie &$format=json
lub &$format=xml
do końca swojego identyfikatora użytkownika podczas testowania za pomocą przeglądarki. Nie koliduje z innymi oczekiwanymi zachowaniami podczas korzystania z klienta innego niż przeglądarka, w którym można ustawić własne nagłówki.
Możesz użyć jak poniżej:
GlobalConfiguration.Configuration.Formatters.Clear();
GlobalConfiguration.Configuration.Formatters.Add(new JsonMediaTypeFormatter());
Wystarczy dodać te dwa wiersze kodu do klasy WebApiConfig
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
//add this two line
config.Formatters.Clear();
config.Formatters.Add(new JsonMediaTypeFormatter());
............................
}
}
Po prostu zmienisz App_Start/WebApiConfig.cs
tak:
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}"
);
}
Z MSDN Budowanie aplikacji jednostronicowej za pomocą ASP.NET i AngularJS (około 41 minut).
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();
}
Powinien być aktualny, próbowałem i działało.
Minęło trochę czasu, odkąd pytanie zostało zadane (i udzielono odpowiedzi), ale inną opcją jest zastąpienie nagłówka Accept na serwerze podczas przetwarzania żądania za pomocą programu MessageHandler, jak poniżej:
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);
}
}
Gdzie someOtherCondition
może być cokolwiek, w tym typ przeglądarki itp. Dotyczy to przypadków warunkowych, w których tylko czasami chcemy zastąpić domyślną negocjację treści. W przeciwnym razie, podobnie jak w przypadku innych odpowiedzi, wystarczy po prostu usunąć niepotrzebne formatyzatory z konfiguracji.
Oczywiście musisz go zarejestrować. Możesz to zrobić globalnie:
public static void Register(HttpConfiguration config) {
config.MessageHandlers.Add(new ForceableContentTypeDelegationHandler());
}
lub na podstawie trasy po trasie:
config.Routes.MapHttpRoute(
name: "SpecialContentRoute",
routeTemplate: "api/someUrlThatNeedsSpecialTreatment/{id}",
defaults: new { controller = "SpecialTreatment" id = RouteParameter.Optional },
constraints: null,
handler: new ForceableContentTypeDelegationHandler()
);
A ponieważ jest to moduł obsługi komunikatów, będzie działał zarówno na końcach potoku, jak i na żądanie, podobnie jak HttpModule
. Możesz więc łatwo potwierdzić zastąpienie niestandardowym nagłówkiem:
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;
}
}
Oto najprostszy sposób, którego użyłem w swoich aplikacjach. Dodaj podane poniżej 3 wiersze kodu App_Start\\WebApiConfig.cs
w Register
funkcji
var formatters = GlobalConfiguration.Configuration.Formatters;
formatters.Remove(formatters.XmlFormatter);
config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/json"));
Internetowy interfejs API Asp.net automatycznie serializuje Twój zwracany obiekt do JSON, a gdy application/json
jest dodawany w nagłówku, aby przeglądarka lub odbiornik zrozumieli, że zwracasz wynik JSON.
WebApiConfig to miejsce, w którym możesz skonfigurować, czy chcesz wyświetlać dane w formacie json czy xml. domyślnie jest to xml. w funkcji rejestru możemy użyć HttpConfiguration Formatters do sformatowania wyjścia. System.Net.Http.Headers => MediaTypeHeaderValue („text / html”) jest wymagany, aby uzyskać wynik w formacie json.
Korzystając z odpowiedzi Felipe Leusina od lat, po ostatniej aktualizacji bibliotek podstawowych i Json.Net, natrafiłem na System.MissingMethodException
: SupportedMediaTypes. Rozwiązaniem w moim przypadku, miejmy nadzieję, pomocnym dla innych osób, które doświadczają tego samego nieoczekiwanego wyjątku, jest instalacja System.Net.Http
. NuGet najwyraźniej usuwa go w niektórych okolicznościach. Po ręcznej instalacji problem został rozwiązany.
Jestem zdziwiony, widząc tak wiele odpowiedzi wymagających kodowania, aby zmienić pojedynczy przypadek użycia (GET) w jednym interfejsie API zamiast używania odpowiedniego narzędzia, które musi być zainstalowane raz i może być użyte dla dowolnego interfejsu API (własnego lub zewnętrznego) i wszystkich przypadków użycia.
Dobra odpowiedź brzmi: