Lucian Maran

home

Afisarea raspunsului oferit de Web API in JSON in loc de XML

15 Feb 2014

Descrierea problemei

Sa definesc intai ce problema vreau sa rezolv. Pentru aceasta am sa creez o aplicatie ASP.NET WebApi cu setarile default:

Fara nicio alta setare suplimentara, lansez aplicatia in executie si accesez endpoint-ul: /api/values de pe Chrome, FF si IE. Sub fiecare poza am atasat:

Chrome

Chrome headers:

Firefox

FF headers:

IE

IE request header:

De aici se nasc cateva intrebari:

La toate aceste intrebari am sa incerc sa raspund mai jos.

Identificarea cauzei

Implicit, serviciul WebApi stie sa furnizeze raspunsul in ambele tipuri de formate (XML, JSON). La primirea unui request, acesta inspecteaza proprietatea Accept din header-ul HTTP (vezi valoarea de sub fiecare poza) si ii raspunde clientului (browser-ului) in functie de "preferinta" setata in acest atribut:

Obs: In cazul de fata, atributul Content-Type este este atributul prin care server-ul comunica clientului tipul datelor returnate. Acelasi atribut poate fi folosit si de catre client, in acelasi scop, atunci cand are date de transmis server-ului (POST). Alte detalii despre Accept si Content-Type am notat aici.

Solutia 0: Adauga in Windows registry un MIME Type corespunzator (doar pt. IE)

Am notat-o ca fiind "solutia 0" fiindca, de fapt, IE primeste deja datele in format JSON. Deci aici nu avem o problema cu "comutarea" din XML in JSON ci mai degraba cu afisarea acestor date pe ecran.

IE se bazeaza pe MIME Type-urile din Windows si cum Windows-ul nu contine implicit un MIME Type pt. JSON, IE-ul nu randeaza raspunsul primit ci lasa aceasta sarcina pe seama utilizatorului (propunandu-i un download).

Partea buna este ca in Windows poti adauga propriile MIME Type-uri. Acest lucru se poate face adaugand doua chei in registry. O poti face manual dar cea mai simpla varianta este urmatoarea (detalii aici):

  1. Copiaza textul de mai jos intr-un fisier de tip text cu extensia .reg

    [HKEY_CLASSES_ROOT\MIME\Database\Content Type\application/json]
    "CLSID"="{25336920-03F9-11cf-8FD0-00AA00686F13}"
    "Encoding"=hex:08,00,00,00
    
    [HKEY_CLASSES_ROOT\MIME\Database\Content Type\text/json]
    "CLSID"="{25336920-03F9-11cf-8FD0-00AA00686F13}"
    "Encoding"=hex:08,00,00,00
    
  2. Executa (dublu-click) fisierul de mai sus.

In acest moment IE stie ca toate raspunsurile care contin in atributul Content-Type valoarea application/json sau text/json le poate randa ca pe orice text obisnuit:

Solutia 1: Modifica codul WebAPI a.i. sa returneze JSON in loc de XML

Asa cum am vazut mai sus, pentru IE nu trebuie sa modific nimic. Fie ca este descarcat intr-un fisier, fie ca este afisat in browser (cu un MIME type configurat in prealabil), raspunsul primit de IE de la WebApi este JSON. Asta pt. ca WebApi returneaza JSON by default si XML doar daca i se cere explicit.

Prin atributul Accept, un browser poate sa ceara ca datele sa-i fie livrate intr-un anumit format, dar server-ul poate sa ignore aceasta cerere/propunere si sa returneze datele in ce format doreste. Asadar, pt. Chrome si FF putem folosi una din cele 2 abordari:

1.1. Dezactivarea "XML Formatter"-ului din aplicatia WebApi.

Odata serializatorul de XML eliminat, server-ul nu mai are alternativa si va raspunde cu singurul serializator disponibil (JSON). Pot face asta in mai multe moduri:

 config.Formatters.Remove(config.Formatters.XmlFormatter);
 config.Formatters.Clear();
 config.Formatters.Add(new XmlMediaTypeFormatter());
 config.Formatters.Add(new JsonMediaTypeFormatter());
 config.Formatters.Add(new FormUrlEncodedMediaTypeFormatter());

Observatii: - formattere-le sunt procesate in ordinea in care sunt adaugate si se activeaza doar prima care se potriveste - adaugand XML inainte de JSON pot face ca IE-ul sa primeasca un XML - elimin cu totul procesul prin care se "negociaza" un anumit formatter (este solutia cea mai performanta, detalii in articolul lui Fillip W.)

1.2. Selectarea unui anumit Formatter (JSON/XML) din query string

 for xml : http://localhost:16600/api/values/?type=xml
 for json: http://localhost:16600/api/values?type=json

Solutia 2: Modifica setarile browser-ului (atributul Accept)

Daca nu pot sau nu doresc sa modific codul aplicatiei, atunci varianta care imi ramane este sa modific setarile browser-ului. Sau, mai precis, valoarea atributului Accept.

IE

Chrome

FF

Daca ai ajuns pana in acest punct, inseamna ca in IE si Chrome poti vizualiza raspunsul default oferit de WebApi in format JSON, pe cand FF il afiseaza inca in XML. Solutia pt. acest scenariu am preluat-o din articolul lui Brock Allen:

Rezultatul acestei modificari trebuie sa arate asa:

...si testul care iti confirma ca raspunsul este cel asteptat:

[update] Daca te intereseaza sa citesti despre o afisare "mai prietenoasa", in browser, a unui obiect JSON (culori, indentare, grupare etc) o poti face aici.

comments powered by Disqus