WebHttp Services s sebou přínáší další zajímavou funkcionalitu, kterou si na následujících několika řádcích představíme. V minulých dílech jsem komunikoval se službou pouze prostřednictvím xml requestů a výsledkem byl vždy i xml response. Pokud služby nejsou nijak nastaveny, jejich defaultní chování je právě zabalit response do xml.

Pojďme se tedy podívat jak ovlivnit výsledný formát odpovědi.

První důležitou informací je, že pokud pošlu dotaz ve formátu XML či JSON, tak ho vždy dokáže moje služba zpracovat i v případě, že bude v konfiguračním souboru web.config nastaveno automaticFormatSelectionEnabled="false". Toto nastavení se týká pouze odchozích (response) zpráv !

V mojí aplikaci jsem si vytvořil novou metodu nazvanou AddProduct, na které budu demonstrovat použití jednotlivýc způsobů k tomu aby jsme docílil požadovaného výsledku:

Eshop.Service

[Description("Vlozi produkt do kolekce")]
[WebInvoke(UriTemplate = "/AddProduct", Method = "POST")]
public Product AddProduct(Product product)
{
product.ID = FakeDatabase.Products.Max(p => p.ID) + 1;
FakeDatabase.Products.Add(product);
return product;
}

Eshop.Client

private static void AddProduct(Product productToCreate)
{
using (HttpClient client = new HttpClient(URI))
{
HttpContent content = HttpContentExtensions.CreateDataContract<Product>(productToCreate);
// poslu pozadavek POST na adresu http://localhost:8090/Eshop/AddProduct
using (HttpResponseMessage response = client.Post("AddProduct", content))
{
Console.WriteLine("Response:");
Console.WriteLine(response.Content.ReadAsString());
}
}
}

Zde si vytvořím metodu AddProduct, kde pouze zavolám mojí nově vytvořenou metodu na straně služby. Než ovšem porvedeme zavolání mojí metody nastavíme ve web.configu hodnotu automaticFormatSelectionEnabled na false

automaticFormatSelectionEnabled="false"

Po zavolání AddProduct, tedy pošleme na službu XML a služba nám vrátí rovněž XML (defaultní chování)

image

Pokud ovšem někdo pošle dotaz ve formátu JSON tak jak jsem uvedl výše, služba se s ním lehce vypořádá a výsledek bude stejný. Akorát v metodě AddProduct na straně klienta použíjeme HttpContentExtensions.CreateJsonDataContract místo původního ttpContentExtensions.CreateDataContract. Pokud budu chtít odpovídat ve formátu JSON, stačí pouze nastavit vlastnost ResponseFormat atributu WebInvoke na WebMessageFormat.Json. Z předchozích pár řádků vyplývá, že pokud pošleme dotaz v jakémkoliv formátu (xml nebo json), odpověd bude mít vždy takový tvar jaký bude uveden ve vlastnosti ResponseFormat (default: XML)

automaticFormatSelectionEnabled="true"

Pokud ovšem nastavíme automaticFormatSelectionEnabled na true, bude chování trošku odlišnější. Při volbě formátu pro odchozí zprávu se postupuje následujícími kroky:

  1. WCF se podívá na vlastnost AcceptHeader objektu request, pokud nenajde odpovídající honodtu formátu podívá se dále na …
  2. vlastnost ContentType objektu request, pokud nenajde odpovídající hodnotu formátu podívá se dále na …
  3. hodnotu ResponseFormat odpovídající operace

Tzn. v našen případě, když pošleme dotaz ve formátu XML, vrátí se nám odpověd v XML, pokud bude požadavek v JSON, rovněž i odpověď bude v JSON.

Co když ale budeme chtít poslat dotaz ve formátu XML, ale jako odpověď budeme vyžadovat JSON? Jak na to? Když se podíváte o pár řádků výše, podle čeho WCF rozhoduje o formátu odpovědi, tak na prvním místě je AcceptHeader a hned za ním ContentType. My když pomocí CreateDataContract či CreateJsonDataContract vytvoříme objekt HttpContent, tak v něm je nastaven pouze ContentType bud na “application/xml” nebo “application/json” tzn. že pomocí AcceptHeader můžeme ovlivnit výstupní formát tím, že upravíme hlavičku dotazu. Na následujícím kódu můžete vidět jak na to:

private static void AddProduct(Product productToCreate)
{
using (HttpClient client = new HttpClient(URI))
{
using (HttpRequestMessage request = new HttpRequestMessage("POST", "AddProduct"))
{
// do hlavicky pridam informace o vystupnim formatu
request.Headers.Accept.AddString("application/xml");
// vytvorim si obsah ktery budu posilat
request.Content = HttpContentExtensions.CreateJsonDataContract<Product>(productToCreate);
// poslu pozadavek na adresu http://localhost:8090/Eshop/AddProduct
using (HttpResponseMessage response = client.Send(request))
{
Console.WriteLine("Response:");
Console.WriteLine(response.Content.ReadAsString());
}
}
}
}

Vytvořím si pouze objekt HttpRequestMessage, kde specifikuji o jakou operaci se jedná a na jakou adresu ten dotaz budu posílat. Pak přidám do hlavičky informací o formátu výstupu a nakonec tento požadavek odešllu. Jak můžete vidět, vytvářím požadavek v JSON formátu, ale výsledek chci ve formátu xml

image

V poslední ukázce se podíváme na možnost jak si explicitně zvolit výstupní formát. pro tuto ukázku použíjeme již vytvořenou metodu GetProducts, které přidáme parametr nazvaný format, podle kterého si bude moct klient specifikovat v jakém formátu data očekává

[WebGet(UriTemplate = "/Products?format={format}")]
public ProductCollection Products(string format)
{
if (string.Equals("json", format, StringComparison.OrdinalIgnoreCase))
WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;
return FakeDatabase.Products;
}

Přidáním parametru format, jsme musely upravit vlastnost UriTemplate a přidat příslušnou podmínku. Pokud je hodnota parametru format rovna json, nastavím pomocí WebOperationContext třídy Format pro odchozí zpráv na JSON, jinak nechám defaultní hodnotu (XML). Na straně klienta musíme upravit naší metodu GetProducts následovně: (pouze přidáme informace o formátu)

private static void GetProducts(string format)
{
// ujistete se ze vase adresa konci lomitkem !!!
using (HttpClient client = new HttpClient(URI))
{
// poslu pozadavek GET na adresu http://localhost:8090/Eshop/Products
HttpResponseMessage response = client.Get("Products?format=" + format);

Console.WriteLine("Response: [format={0}]", format);
Console.WriteLine(response.Content.ReadAsString());
Console.WriteLine();
}
}

Pro otestování zavolám GetProducts(“json”) a GetProducts(“default”) a výsledkem bude při prvním volání odpověď ve formátu json, podruhé ve formátu xml

image

Závěr

V dnešním článku jsme si ukázali jak se chovají WebHttp services při zpracování požadavků v XML či JSON formátu, poukázaly na důležitost nastavení atributu automatiFormatSelectionEnabled ve web.config souboru a celé to zakončili ukázkou jak ovlivnit formát odchozí zprávy. V dalším článku se podíváme na možnosti jak zpracovávat výjimky.