Routování při použití WebHttp Services může být velice nápomocné při snaze rozdělit funkcionalitu službu na menší části, kde každá část bude mít svojí speciální adresu. Jak provést rozdělení a příslušné napamování si ukážeme na následující ukázce.

Máme vytvořenou službu, která nabízí pro jednoduchost pouze dvě metody

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class EshopService
{
[WebGet(UriTemplate = "/Products?format={format}")]
[Description("Vrati seznam vsech produktu")]
public ProductCollection FindAll(string format)
{
if (string.Equals("json", format, StringComparison.OrdinalIgnoreCase))
WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;

return FakeDatabase.Products;
}

[WebGet(UriTemplate = "/Product/{id}")]
[Description("Najde produkt podle zadaneho id")]
public Product Find(string id)
{
int parsedId = 0;
if (int.TryParse(id, out parsedId))
return FakeDatabase.Products.Where(p => p.ID == parsedId).FirstOrDefault();

return null;
}
}

Pro zobrazení všech produktů zadáme do prohlížeče adresu http://localhost:8090/Eshop/Products. Jakmile budeme chtít ovšem zobrazovat např. objednávky, uživatele, kategorie, apod. stane se naše třída EshopService velice nepřehlednou a tudíž složitější na údržbu. Vytvořme si tedy novou třídu nazvanou OrderService, která bude sloužit pro práci s objednávkami. Stávající třídu EshopService přejmenujeme na ProductService.

Ještě před vytvořením nové třídy by jsme si mohly vytvořit rozhraní, ve kterém budeme specifikovat příslušné metody. Rozhraní si můžeme pojmenovat IEntity a vypadá následovně:

public interface IEntity<out TColl, out TEntity> where TColl : Collection<TEntity>
{
/// <summary>
/// Vrati seznam vsech polozek
/// </summary>
/// <param name="format">format (json, xml)</param>
/// <returns></returns>
TColl FindAll(string format);

/// <summary>
/// Podle id nalezne prislusnou polozku
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
TEntity Find(string id);
}

A nyní již implementace zmiňované třídy OrderService. Všimněme si, že oproti původní EshopService je upravená adresa (UriTemplate) atributu WebGet. Jelikož namapujeme adresu Orders na třídu OrderService, není potřeba aby byla adresa operace ve tvaru /Orders/id ale stačí pouze id či ?format=format…

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class OrderService : IEntity<OrderCollection, Order>
{
#region Implementation of IEntity<out OrderCollection,out Order>

[WebGet(UriTemplate = "?format={format}")]
[Description("Vrati seznam vsech objednavek")]
public OrderCollection FindAll(string format)
{
if (string.Equals("json", format, StringComparison.OrdinalIgnoreCase))
WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;

return FakeDatabase.Orders;
}

[WebGet(UriTemplate = "{id}")]
[Description("Najde objednavku podle zadaneho id")]
public Order Find(string id)
{
int parsedId = 0;
if (int.TryParse(id, out parsedId))
return FakeDatabase.Orders.Where(p => p.ID == parsedId).FirstOrDefault();

return null;
}

#endregion
}

a přejmenování EshopService na ProductService a úprava UriTemplate (viz. OrderService)

[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class ProductService : IEntity<ProductCollection, Product>
{
[WebGet(UriTemplate = "?format={format}")]
[Description("Vrati seznam vsech produktu")]
public ProductCollection FindAll(string format)
{
if (string.Equals("json", format, StringComparison.OrdinalIgnoreCase))
WebOperationContext.Current.OutgoingResponse.Format = WebMessageFormat.Json;

return FakeDatabase.Products;
}

[WebGet(UriTemplate = "{id}")]
[Description("Najde produkt podle zadaneho id")]
public Product Find(string id)
{
int parsedId = 0;
if (int.TryParse(id, out parsedId))
return FakeDatabase.Products.Where(p => p.ID == parsedId).FirstOrDefault();

return null;
}
}

Když jsme si vytvořily takto dvě třídy byly by ideální aby se po zadání určitých dotazů provedly příslušné akce:

Původní EshopService byla tedy rozdělena na ProductService a OrderService a v posledním kroku můžeme provést namapování, tak aby naše směrování bylo úspěšné. Otevřeme si soubor Global.asax, kde v metodě RegisterRoutes provedeme příslušné namapování

private void RegisterRoutes()
{
var factory = new WebServiceHostFactory();

// Edit the base address of Service1 by replacing the "Service1" string below
RouteTable.Routes.Add(new ServiceRoute("Products", factory, typeof(ProductService)));
RouteTable.Routes.Add(new ServiceRoute("Orders", factory, typeof(OrderService)));
}

Závěr

Jak můžeme vidět, implementace routování byla v naší aplikaci na dva řádky, takže nic moc složitého. V dalších dílech si ukážeme jak pracovat s jinými formáty než jenom xml či json, jak cachovat data, apod.