Poznáváme C# a Microsoft .NET – 68. díl – WebRequest a WebResponse

Náš zájem je dnes stejně jako v díle předchozím zamířen na aplikace pracující v síti. Dnes se ale podíváme na to jakým způsobem je možné na platformě .NET implementovat síťové aplikace, využívající architekturu požadavek/odpověď.

Architektura požadavek/odpověď v .NET

I přestože je přístup k síťovým zdrojům pomocí třídy WebClient, kterou jsme si představovali v minulém díle, velmi jednoduchý, často při implementaci síťových aplikací narazíme na situace, kde pro nás bude její vysoká míra abstrakce omezující. V takovýchto případech „sáhneme“ po dvojici tříd WebRequest a WebResponse ze jmenného prostoru System.Net. Tyto třídy pro nás představují cestu k implementaci aplikací na základě přístupu požadavek/odpověď, kde je na základě URI proveden požadavek na vzdálený zdroj a ten je nám, pokud vše dobře zafunguje, v podobě odpovědi navrácen.

Implementace zmíněného přístupu pomocí tříd WebRequest a WebResponse je založen na principu datových proudů a využívání abstraktních tříd či rozhraní. Obě uvedené třídy jsou třídami abstraktními, tudíž není možné vytvořit jejich instance a jsou jen obecnými bázovými třídami, z nichž jsou odvozeny implementace pro konkrétní síťové protokoly. Cestou k vytvoření objektu představující požadavek na konkrétní vzdálený zdroj je použití statické tovární metody Create třídy WebRequest .

Po tomto vytvoření jsme schopni na vzniklém objektu pomocí jeho metody získat objekt představující odpověď. Pokud v naší aplikaci nepotřebujeme využívat vlastností jednotlivých protokolů (např. HTTP) můžeme pracovat pouze s rozhraním tříd WebRequest a WebResponse a tím tedy pracovat pouze na obecné úrovní požadavek/odpověď. Standardně jsou v .NET frameworku verze 1.1 implementovány třídy ovladačů pro protokoly HTTP, HTTPS a FILE. V .NET frameworku verze 2.0 ještě přibyla podpora pro protokol FTP.

Jak by mohl vypadat jednoduchý příklad, který pro přístup ke vzdálenému zdroji využívá tříd WebRequest a WebResponse ukazuje následující příklad.

//nacteni URI, na ktery bude proveden pozadavek
Console.Write("Zadejte URI (napr.
) : ");
string uri = Console.ReadLine();
//vytvoreni instance pozadavku
WebRequest  request = WebRequest .Create(uri);
WebResponse response = null;
StreamReader reader = null;
try
{
  //vyslani pozadavku a ziskani odpovedi
  response = request.GetResponse();
  //ziskani datoveho proudu odpovedi
  Stream strm = response.GetResponseStream();
  reader = new StreamReader(strm);
  //nacteni textu odpovedi
  string content = reader.ReadToEnd();
  Console.WriteLine(content);
}
catch(WebException ex)
{
  Console.WriteLine("Doslo k vyjimce : {0}", ex.ToString());
}
finally
{
  if (reader != null)
  {
    reader.Close();
  }
  if (response != null)
  {
    response.Close();
  }

}

Tovární metoda Create na základě identifikátoru protokolu v URI vrací objekt požadavku pro daný protokol, ke kterému je standardně přistupováno přes rozhraní abstraktní třídy WebRequest . Vytvořením objektu požadavku není ještě skutečný síťový požadavek odeslán. Děje se tomu až v čase získávání objektu odpovědi, což učiníme zavoláním metody GetResponse na objektu požadavku. Pro získání datového proudu obdržené odpovědi využijeme metodu GetResponseStream a následně jej nějakým způsobem zpracujeme. Po tom co získanou odpověď zpracujeme, tak nikdy nesmíme zapomenout na uzavření spojení, což zařídíme metodou Close na objektu odpovědi.

Specifické vlastnosti protokolu HTTP

Z důvodu zachování určité míry abstrakce se často pracuje pouze na úrovní použití rozhraní základních tříd WebRequest a WebResponse. Metoda Create vrací odkaz na obecný typ požadavku WebRequest a metoda GetResponse zase na obecný typ odpovědi WebResponse. Tím je dosažena nezávislost na síťovém protokolu ve zdrojovém kódu.

To jací specifičtí potomci tříd WebRequest a WebResponse jsou ve skutečnosti používány je závislé pouze na použitém URI, který je předán metodě Create. Ve skutečnosti tovární metoda Create v případě, že je jako identifikátor protokolu v URI uvedeno http://, vrátí instanci třídy HttpWebRequest a metoda GetResponse vrací instanci třídy HttpWebResponse.

V případě použití identifikátoru protokolu file:// jsou zase vráceny specializované instance FileWebRequest a FileWebResponse. Takže pokud chceme využít specifické vlastnosti protokolu HTTP, využijeme těchto specializovaných potomků. Toho jednoduše docílíme pomocí přetypování směrem dolů, jak ukazuje následující příklad.

//nacteni URI, na ktery bude proveden pozadavek
Console.Write("Zadejte adresu pro HTTP pozadavek (napr.
www.zive.cz) : ");
string uri = "http://" + Console.ReadLine();
//vytvoreni instance pozadavku
HttpWebRequest  request = (HttpWebRequest ) WebRequest .Create(uri);
//nastaveni specificke vlastnosti HTTP pozadavku
request.UserAgent = "Pokusny klient";
HttpWebResponse response = null;
try
{
  response = (HttpWebResponse)request.GetResponse();
  //precteni specifickych vlastnosti HTTP odpovedi
  Console.WriteLine("Last modified : {0}", response.LastModified);
  Console.WriteLine("Status code : {0}", response.StatusCode);
}
finally
{
  if (response != null)
  {
    response.Close();
  }
}

Tím, že jsme provedli přetypování na specializované implementace tříd WebRequest /WebResponse jsme získali možnost pomocí jejich instančních vlastností specifikovat (v případě požadavku) a číst (v případě odpovědi) specifické informace obsažené v záhlaví. Takže v ukázkovém zdrojovém kódu jsme například požadavku nastavili vlastnost USER AGENT sloužící k podání informací o použitém prohlížeči a z objektu odpovědi jsme přečetli datum poslední modifikace a kód stavu.

K záhlaví požadavku čí odpovědi lze přistupovat i na obecné úrovni tříd WebRequest a WebResponse a to pomocí jejich instanční vlastnosti Headers, která je typu kolekce WebHeaderCollection. Pomocí prvků této kolekce jsme schopni přistupovat i k těm informací v záhlaví, které nejsou k dispozici pomocí API na specializovaných potomcích. Samozřejmě vlastnost Headers můžete využít nejen u obecných tříd WebRequest a WebResponse, ale i u jejich odvozených tříd (např. HttpWebRequest ).

//nacteni URI, na ktery bude proveden pozadavek
Console.Write("Zadejte URI (napr.
) : ");
string uri = Console.ReadLine();
//vytvoreni instance pozadavku
WebRequest  request = WebRequest .Create(uri);
WebResponse response = null;
try
{
  //vyslani pozadavku a ziskani odpovedi
  response = request.GetResponse();
  for (int i = 0; i < response.Headers.Count; i++)
  {
    string headerKey = response.Headers.GetKey(i);
    string headerValue = response.Headers[i];
    Console.WriteLine("{0} - {1}", headerKey, headerValue);
  }
}
catch(WebException ex)
{
  Console.WriteLine("Doslo k vyjimce : {0}", ex.ToString());
}
finally
{
  if (response != null)
  {
    response.Close();
  }
}

Zdrojové kódy příkladů ke článku jsou ke stažení zde.

Diskuze (1) Další článek: Kdo miluje Microsoft Office?

Témata článku: , , , , , , , , ,