Jak uzyskać ASP.NET Web API do zwracania JSON zamiast XML za pomocą Chrome?


1220

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ę?


8
Tutaj jest dyskusja, aby zwracanie JSON było domyślnym zachowaniem: github.com/aspnet/Mvc/issues/1765
Natan

Odpowiedzi:


1736

Właśnie dodałem następujące elementy w App_Start / WebApiConfig.csklasie 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ć XMLpo wysłaniu text/xml.

Jeśli musisz mieć odpowiedź Content-Typejak application/jsonnależy sprawdzić odpowiedź Todda poniżej .

NameSpaceużywa System.Net.Http.Headers.


115
Jest to zaskakująco przeoczona odpowiedź i chociaż pierwotne pytanie nie było całkowicie jasne, bezpośrednio JSON stanowi domyślną odpowiedź dla przeglądarki internetowej (która wysyła Akceptuj: tekst / HTML). Dobra robota.
gregmac 15.01.2013

16
+1 Zdecydowanie najlepsza odpowiedź. Wyobrażam sobie, że istnieje mnóstwo osób, które decydują się całkowicie usunąć XML tylko dlatego, że nie widzą JSON w przeglądarce.
Derek Hunziker,

3
Odkryłem, że kiedy to zrobiłem, dane dostarczone przez stronę trzecią ze znacznikami podziału HTML zakończyły się zwrotami karetki. JSON był wtedy nieprawidłowy. Lepiej użyć zaakceptowanej odpowiedzi, jeśli dotyczy to Ciebie.
Stonetip

23
Zauważ, że Content-Typenagłówek odpowiedzi nadal będzie text/html.
Mrchief

78
To jest okropne. Nagłówkiem typu treści odpowiedzi powinna być application / json. To „rozwiązanie” sprawia, że ​​jest to tekst / HTML.
skuteczny

501

Jeśli zrobisz to w WebApiConfig, domyślnie otrzymasz JSON, ale nadal pozwoli ci zwrócić XML, jeśli podasz text/xmljako Acceptnagłó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.


51
Uwaga: oryginalne zachowanie jest prawidłowe. Żądania Chrome application/xmlz priorytetem 0,9 i */*priorytetem 0,8. Usuwając application/xmlusuwasz 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.
wsie

11
Czy to ja, czy pierwsze zdanie jest niepoprawne? Wygląda na to, że kod całkowicie usuwa XML, a nie tylko zmienia domyślny.
NickG

6
@NickG: rozwiązanie, które jest tutaj pomijane, a IMHO jest znacznie lepszą opcją (zachowanie aplikacji / xml) to rozwiązanie zaproponowane przez Felipe Leusina poniżej na tej stronie. Korzystanie z config.Formatters.XmlFormatter.SupportedMediaTypes.Add (new MediaTypeHeaderValue („text / html”));
Cohen

1
Jak więc to zrobić przez konfigurację sieci, aby domyślnie otrzymywaliśmy json i XML na żądanie?
Kyle

4
@Felipse Leusin odpowiedź poniżej jest w rzeczywistości krótsza i działa lepiej.
Ken Smith

313

Korzystanie z RequestHeaderMapping działa jeszcze lepiej, ponieważ ustawia również Content-Type = application/jsonw 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"));

6
Jest to najbardziej uproszczone i najprostsze rozwiązanie, a Fiddler wykrywa również typ zawartości zwracany jako josn.
Steve Johnson

4
Miły! Gdzie sugerujesz umieszczenie tego w kodzie?
Tim Abell

9
Powinien przejść do WebApiConfig.cs
Animesh

9
Pracował dla mnie. Musiałem dodać przy użyciu System.Net.Http.Formatting;
bbsimonbb

1
Łączenie dla własnej wygody: ta odpowiedź ładnie współgra z innym etapem konfiguracji, który zwykle wykonuję: stackoverflow.com/a/28337589/398630 .
BrainSlugs83

308

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

24
W konstruktorze dodaj, this.SerializerSettings.Formatting = Formatting.Indented;jeśli chcesz, aby był ładnie wydrukowany bez rozszerzenia przeglądarki.
Alastair Maw

10
dlaczego miałbyś chcieć ładnie drukować przez drut?
skuteczny

8
Nie jest @ dmit77 „s Odpowiedź lepsze (bardziej zwięzły) niż ten?
H.Wolper

8
@eddiegroves, których nie chcesz ładnie drukować za pośrednictwem drutu. Chcesz, aby serwer wysyłał najmniejszą liczbę bitów przewodowo (tj. Bez spacji). Następnie chcesz, aby przeglądarka ładnie go sformatowała, z dodatkami i tym podobnymi. JavaScript zwykle musi
parsować

13
Dla szukających pracowników: nie zapomnij dodać using System.Net.Http.Formattingiusing Newtonsoft.Json
Berriel,

186

Szybka porada MVC4 # 3 - Usuwanie formatera XML z ASP.Net Web API

W Global.asaxdodać 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();
}

9
Działa - o wiele ładniej jest mieć JSON jako domyślny zamiast XML.
Whitneyland

5
ale czy nadal możesz zwrócić xml?
Thomas Stock

99
Przetestowałem to i nie możesz. To usuwa obsługę XML. Ostrzegamy, drodzy ludzie Google
Thomas Stock

3
Jeśli spojrzysz na moją odpowiedź poniżej, pozwoli to na zwrócenie xml, jeśli chcesz, ale pozwoli stronie odpowiedzieć JSON do przeglądarki
Glenn Slaven

3
@GlennSlaven tak, twoja odpowiedź powinna być ta oznaczona jako poprawna.
radu florescu

114

W pliku WebApiConfig.cs dodaj na końcu funkcji rejestru :

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

Źródło .


Czy XmlFormatter jest nowy w MVC4?
Glenn Slaven

1
W MVC5 można to zrobić, zastępując config GlobalConfiguration.Configuration
Steven

4
Jest to zdecydowanie najlepsza opcja dla projektu, który musi obsługiwać tylko JSON i pod żadnym pozorem nie może emitować XML.
Luc C

1
config.Formatters.Add (config.Formatters.JsonFormatter);
Cas Bloem

3
To straszne. - To zawsze zwróci JSON bez względu na wszystko, nawet jeśli klient specjalnie poprosi o XML w nagłówku Content-Type.
BrainSlugs83

94

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

2
Świetny Jakiej metody oczekujesz od parametru? jak localhost: 61044 / api / values ​​/ getdate? json = true, date = 2012-08-01
LT.Nolo

jakiego rodzaju format danych interfejsu API zwraca domyślnie. czy to json czy webapi? dzięki
Thomas

54

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 Acceptlub Content-Typeżądanie. Ponieważ akcja nie jest zakodowana w celu zwrócenia określonego formatu, możesz ustawić Accept: application/json.


6
„abym mógł zobaczyć w przeglądarce”
Spongman

1
@Spongman, tak, możesz. Ale użyj rozszerzenia takiego jak REST Client - większość przeglądarek ma takie podobne. Bezpośrednie wpisywanie adresu URL w przeglądarce to 1. Zbyt ograniczenie (brak kontroli nad nagłówkami, nie można wysyłać danych itp.); 2. Niepoprawnie - przeglądarka nie korzysta z interfejsu API sieci, ponieważ jest przeznaczony do konsumpcji - nie można na nim polegać, testując go poprawnie. Tak więc, dobry dodatek klienta REST to naprawi.
Ivaylo Slavov,

45

Ponieważ pytanie dotyczy Chrome, możesz uzyskać rozszerzenie Postman, które pozwala ustawić typ zawartości żądania.

Listonosz


W przeglądarce Firefox po prostu przejdź do about: config, wyszukaj plik accept.default i zmień zawartość network.http.accept.defaultkonfiguracji na text/html,application/xhtml+xml,application/json;q=0.9,application/xml;q=0.8,*/*;q=0.7.
Bjartur Thorlacius

Lub jeszcze lepiej, text/html,application/xhtml+xml;q=1.0,*/*;q=0.7aby uniknąć błędnych hostów, takich jak Bitbucket, przed przypadkowym udostępnieniem przeglądarki JSON zamiast HTML.
Bjartur Thorlacius

Adres URL jest martwy. Nowym jest chrome.google.com/webstore/detail/postman/… .
Falcon Momot,

35

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.


2
To było bardzo przydatne. Możesz także użyć UriPathExtensionMapping zamiast QueryStringMapping, jeśli chcesz użyć path.to/item.json
nuzzolilo,

32

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!


1
To najbardziej elastyczna odpowiedź (i naprawdę powinna być domyślną konfiguracją w dzisiejszych czasach). Aby dodać do tej odpowiedzi, JSON jest domyślny, w tym z przeglądarki. Aby wyświetlić XML, dodaj ciąg zapytania
:? Xml

Wypróbowałem wiele strategii. Miałem prosty test zarówno dla XML, jak i JSON, i to wyszło po wyjęciu z pudełka
pat capozzi

23

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.


30
Dlaczego nie skorzystać z przeglądarki? To oczywiste narzędzie do tego.
Anders Lindén,

4
Myślę, że punkt tutaj jest poprawny i ważny - nie powinniśmy nadmiernie poprawiać działającej części aplikacji (infrastruktury MAPI WebAPI), jeśli problem jest spowodowany przez klienta. Rzeczywisty przypadek użycia interfejsu API powinien być właściwie używany (przez podanie poprawnych nagłówków), za co odpowiada aplikacja. Nie zgadzam się jednak z całkowitym odrzuceniem przeglądarki - do testowania dostępnych jest wiele narzędzi dla prawie każdej przeglądarki (na początek uruchom rozszerzenia przypominające klienta).
Ivaylo Slavov,

6
To prawdopodobnie powinien być komentarz.
bonh

17

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


12

Użyłem globalnego filtra akcji, aby usunąć, Accept: application/xmlgdy User-Agentnagłó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.


11

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/jsonmiędzy innymi: Zaawansowany klient REST


10

Prawidłowy format jest zwracany przez formatyzator typu media. Jak wspomnieli inni, możesz to zrobić w WebApiConfigklasie:

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ć ActionFilterAttributei 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 Attributena dekoracji akcji i użyć go [JsonOutput]zamiast [JsonOutputAttribute].


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

3
Chociaż ten kod może odpowiedzieć na pytanie, zapewnienie dodatkowego kontekstu dotyczącego tego, jak i / lub dlaczego rozwiązuje problem, poprawiłoby długoterminową wartość odpowiedzi. Proszę przeczytać ten stackoverflow.com/help/how-to-answer
SR

6

zgodnie z najnowszą wersją ASP.net WebApi 2,

poniżej WebApiConfig.cs, to zadziała

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

6

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.


5

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-8nagłówek w odpowiedzi.

To pozwala na sczepienie &$format=jsonlub &$format=xmldo 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.


5

Możesz użyć jak poniżej:

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

Jeśli tworzysz aplikację WebAPI do przekazywania wiadomości JSON, rozważ tę odpowiedź.
allen1

4

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


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

3

Po prostu zmienisz App_Start/WebApiConfig.cstak:

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

Usunięcie formatyzatora na ogół nie jest dobrym pomysłem, usuwasz funkcje.
naspinski

Właściwie w tym przypadku działa dla mnie dobrze, również wielu innych sugeruje taki sposób. Nauczyłem się tego z książki myview.rahulnivi.net/building-spa-angular-mvc-5 !
vaheeds

2

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.


2

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

2

Oto najprostszy sposób, którego użyłem w swoich aplikacjach. Dodaj podane poniżej 3 wiersze kodu App_Start\\WebApiConfig.csw Registerfunkcji

    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/jsonjest dodawany w nagłówku, aby przeglądarka lub odbiornik zrozumieli, że zwracasz wynik JSON.


1

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. wprowadź opis zdjęcia tutaj


1

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.


-3

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:

  1. Jeśli chcesz tylko poprosić o json lub inny typ zawartości, zainstaluj Żądaj lub podobne narzędzie i zmodyfikuj nagłówek Akceptuj.
  2. Jeśli chcesz również używać POST i ładnie sformatowany plik json, xml itp., Użyj odpowiedniego rozszerzenia testującego API, takiego jak Postman lub ARC .

Niektórzy wolą robić rzeczy bez dodawania wzdęć w postaci dodatkowych narzędzi i bibliotek.
tno2007

Nadal niewłaściwe jest wprowadzanie zmian w interfejsie API tylko dlatego, że ktoś używa niewłaściwego narzędzia do zadania. Przeglądarka internetowa nie została zaprojektowana do testowania interfejsów API, nawet do wyświetlania danych wyjściowych interfejsów API, ale do przeglądania dokumentów. Gorzej, jeśli ktoś myśli, że narzędzie do testowania API jest rozdęte zamiast części obowiązkowego zestawu narzędzi dla dowolnego programisty API, i szczerze mówiąc, dodałbym również programistów front-end, ponieważ muszą oni również współdziałać i eksperymentować z interfejsami API. Prawdopodobnie to też nie wystarczy, ponieważ przeglądarka bez dodatków nie pozwala ustawiać nagłówków, publikować w interfejsie API, a nawet sprawdzać nagłówki odpowiedzi.
user3285954

Rozumiem co mówisz i się nie mylisz. Ale nie na temat, powodem, dla którego dostajesz głos w dół, jest ton, w którym odpowiadasz na pytanie. Brzmisz bardzo wojowniczo i wydaje się, że jesteś deweloperem, który myśli, że wie wszystko, a to jest bardzo niesmaczne. Jestem pewien, że jesteś świetnym programistą, sądząc po twoich odpowiedziach. Ale musisz nauczyć się, szczególnie w środowisku profesjonalnej kontroli jakości, jak to, aby zwracać się do ludzi i przekonywać ich w bardziej przyjazny i ludzki sposób. Być może najpierw odpowiedz, czego chcą, a następnie wyjaśnij lepszy sposób i uzasadnij, dlaczego jest lepszy.
tno2007
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.