Poznáváme C# a Microsoft .NET - 69. díl – Pokročilé využití tříd WebRequest a WebResponse

Třídy WebRequest a WebResponse a jejich využití již po minulém dílu známe a dnes se zaměříme na jejich použití v pokročilejších scénářích, kterými jsou realizace asynchronních požadavků, posílání dat a autentizace.

Asynchronní požadavky

Jistě některé z vás při čtení minulého dílu, který pojednával o získávání vzdálených dat pomocí tříd WebRequest a WebResponse, že by bylo užitečné mít možnost učinit požadavek na vzdálený zdroj asynchronně, tedy ve vlastním vlákně. To se hodí například v případech, kdy se vzdálený zdroj, na který zasíláme požadavek nachází na serveru, jenž je značně zatěžován a tudíž získání odpovědi může být otázka i několika vteřin. Po tuto dobu můžeme chtít nechat naši aplikaci vykonávat další operace a v době získání odpovědi na náš zaslaný požadavek na tuto událost zareagovat příslušnými akcemi.

Pro dosažení tohoto cíle můžeme směle využít metody BeginGetResponse na instanci třídy WebRequest v kombinaci s užitím instance delegáta AsyncCallBack jak ukazuje následující příklad.

/// <summary>
/// Ukazka pouziti tridy WebRequest k realizaci asynchronniho pozadavku
/// </summary>
public class AsyncRequest
{
 public static void Run()
 {
  //nacteni URI, na ktery bude proveden pozadavek
  Console.Write("Zadejte URI (napr.
) : ");
  string uri = Console.ReadLine();
  //vytvoreni instance pozadavku
  WebRequest request = WebRequest.Create(uri);
  try
  {
   AsyncCallback callback = new AsyncCallback(ResponseCallBack);
   //zahajeni asynchronniho vyslani pozadavku
   request.BeginGetResponse(callback, request);
  }
  catch(Exception ex)
  {
   Console.WriteLine("Nastala vyjimka {0}", ex.ToString());
  }
  //cekani na dokonceni asynchronni operace
  Console.ReadLine();
 }

 //obsluzna metoda pro zpracovani asynchronniho pozadavku
 static void ResponseCallBack(IAsyncResult result)
 {
  //ziskani objektu pozadavku, ktery je zpracovavan
  WebRequest request = (WebRequest) result.AsyncState;
  StreamReader reader = null;
  WebResponse response = null;
  if (result.IsCompleted)
  {
   try
   {
    //ukonceni vlakna provadejiciho pozadavek a ziskani vysledku
    response = request.EndGetResponse(result);
    //ziskani datoveho proudu odpovedi
    Stream responseStream = response.GetResponseStream();
    //vypsani vysledku
    reader = new StreamReader(responseStream);
    string content = reader.ReadToEnd();
    Console.WriteLine(content);
   }
   catch(Exception ex)
   {
    Console.WriteLine("Nastala vyjimka {0}", ex.ToString());
   }
   finally
   {
    if (reader != null)
    {
     reader.Close();
    }
    if (response != null)
    {
     response.Close();
    }
   }
  }
 }
}

Zpracování odpovědi je v tomto asynchronním scénáři stejné jako v případě využití asynchronních delegátů, tedy reakcí na dokončení operace pomocí instance delegáta AsyncCallBack. Tuto instanci předáme jako parametr metodě BeginGetResponse a jako druhý parametr předáme objekt, který si po té můžeme v obslužné metodě vyzvednout. V přikladu je předán přímo objekt WebRequest, který je následně v obslužné metodě ResponseCallBack pomocí vlastnosti AsyncState vyzvednut. Pomocí objektu WebRequest je získán objekt WebResponse, představující odpověď, zavoláním metody EndGetResponse, která ukončí provádění asynchronního požadavku. Po té již standardním způsobem přečteme obsah odpovědi.

Zasílání dat

S poměrně velkou pravděpodobností se při implementaci aplikací získávající internetové zdroje dostanete do situace, kdy bude zapotřebí zaslat danému zdroji nějaká data, která budou na vzdáleném serveru zpracována a na jejichž základě vám bude vrácena odpověď. V případě, že budeme využívat protokolu HTTP, tak dvěma hlavními metodami, kterými jsme schopni zmíněná data předat jsou metody GET a POST. Využití metody GET je jednoduché, protože názvy parametrů a jejich hodnoty jsou přímo části URI. Naproti metoda POST využívá hlavičky požadavku a této metody je užito například při odesílání dat z webových formulářů.

To jakou metodu pro poslání dat použijeme jsme schopni při použití třídy WebRequest definovat pomocí její instanční vlastnosti Method. Pro získání datového proudu požadavku, jimž budeme data zasílat použijeme metodu GetRequestStream. Důležité je také nastavit typ zasílaných dat a také jejich velikost, což zajistíme pomocí vlastností ContentType a ContentLength.
Jako inspirace může posloužit následující zdrojový kód.

//nacteni URI
Console.Write("Zadejte URI na kterou budou poslana data : ");
string uri = Console.ReadLine();
//nacteni dat k odeslani
Console.Write("Zadejte data, ktera budou s pozadavkem poslana : ");
string data = Console.ReadLine();
Stream requestStream = null;
Stream responseStream = null;
try
{
 //vytvoreni objektu pozadavku
 WebRequest request = WebRequest.Create(uri);
 //nastaveni metody odeslani dat
 request.Method = "POST";
 //nastaveni velikosti posilanych dat v bajtech
 request.ContentLength = System.Text.Encoding.Default.GetByteCount(data);
 //nastaveni typu obsahu
 request.ContentType = "application/x-www-form-urlencoded";
 //zapsani dat do proudu pozadavku
 requestStream = request.GetRequestStream();
 StreamWriter writer = new StreamWriter(requestStream);
 writer.Write(data);
 writer.Close();
 //ziskani obsahu odpovedi
 responseStream = request.GetResponse().GetResponseStream();
 StreamReader reader = new StreamReader(responseStream);
 string received = reader.ReadToEnd();
 Console.WriteLine(received);
}
catch(Exception ex)
{
 Console.WriteLine("Nastala vyjimka : {0}", ex.ToString());
}
finally
{
 if (requestStream != null)
 {
  requestStream.Close();
 }
 if (responseStream != null)
 {
  responseStream.Close();
 }
}

Všimněte si, že jako typ obsahu je pomocí vlastnosti ContentType nastavena hodnota application/x-www-form-urlencoded, což je hodnota, které je užíváno při zmíněném odesílání formulářových aplikací. Takže stránka na kterou bude vznášen náš požadavek bude moci tato data vyzvednout stejným způsobem jako když přijímá data z odeslaného webového formuláře (tedy pokud bude řetězec představující data ve správném formátu název=hodnota).

Poznámka: Pro možnost vyzkoušení tohoto příkladu je v příkladech ke stažení také jednoduchá ASP .NET stránka, která umí touto formou zaslaná data zpracovat.

Požadavky na zabezpečené zdroje

Ne ke všem zdrojům v síti je možné přistupovat anonymně. Některé webové aplikace vyžadují, aby s sebou požadavky, které na ni směřují nesly informaci o uživateli, který tyto požadavky zasílá. Tyto aplikace pak na základě těchto předaných dat rozhodnou, jestli požadavek na konkrétní zdroj bude autorizován či nikoli.

Samozřejmě i na toto je v .NET frameworku myšleno a objektu WebRequest je možné nastavit výše zmíněné autentikační údaje pomocí vlastnosti Credentials.

Console.Write("Zadejte URI : ");
string uri = Console.ReadLine();
WebRequest request = WebRequest.Create(uri);
Console.Write("Zadejte uzivatele : ");
string user = Console.ReadLine();
Console.Write("Zadejte heslo: ");
string password = Console.ReadLine();
//vytvoreni objektu nesouciho autentikacni udaje
NetworkCredential credential = new NetworkCredential(user, password);
//prirazeni autentikacniho objektu k pozadavku
request.Credentials = credential;
Stream responseStream = null;
try
{
 responseStream = request.GetResponse().GetResponseStream();
 StreamReader reader = new StreamReader(responseStream);
 Console.WriteLine(reader.ReadToEnd());
}
catch(WebException ex)
{
 HttpWebResponse response = (HttpWebResponse) ex.Response;
 if (response.StatusCode == HttpStatusCode.Unauthorized)
 {
  Console.WriteLine("Pristup byl odepren !");
 }
 else
 {
  throw;
 }
  
}
finally
{
 if (responseStream != null)
 {
  responseStream.Close();
 }
}

Zmíněná vlastnost Credentials je typu rozhraní ICredentials a implementací použitou v tomto příkladu je třída NetworkCredential. Při vytváření instance této třídy předáme konstruktoru autentikační údaje, kterými jsou jméno a heslo uživatele. V případě, že se žádost o vzdálený zdroj nezdaří, jsme schopni zjistit, jestli je to z důvodu neudělení autorizace. Výjimka WebException, která je v případě vzniku chyby při provádění požadavku vyhozena, umožňuje získat odkaz na objekt WebResponse po jehož přetypování na HttpWebResponse (pokud tedy používáme k přístupu protokol HTTP) je možné zjistit z jakého důvodu chyba vznikla přečtením stavového kódu odpovědi (vlastnost StatusCode).

Existuje i možnost jak spolu s požadavkem zaslat autentikační údaje uživatele pod jehož kontextem daná aplikace běží (uživatel, který spustil aplikaci). Za účelem získání takovéhoto objektu ICredentials využijeme třídy CredentialCache, jejímž hlavním účelem je uchovávat autentikační údaje pro různé vzdálené zdroje, a její vlastnosti DefaultCredential.

//k autentikaci pouzijeme ucet uzivatele pod nimz bezi tato aplikace
request.Credentials = CredentialCache.DefaultCredentials;

Poznámka: ASP .NET aplikace, která je dodávána spolu s příklady je nakonfigurována tak, že odmítá požadavky od neautorizovaných zdrojů (nastaveno v souboru web.config), tudíž si můžete vyzkoušet, že pokud s požadavkem nezašlete údaje o uživateli váš požadavek bude odmítnut.

Příklady ke článku jsou ke stažení zde.

Témata článku: Software, Microsoft, Programování, Zavolání, Díl, Catch, Dokončené dílo

Určitě si přečtěte

Tesla chce změnit nákladní dopravu. Její elektrický náklaďák má ohromující parametry

Tesla chce změnit nákladní dopravu. Její elektrický náklaďák má ohromující parametry

** Tesla představila elektrický kamion ** Má obdivuhodný výkon i dojezd ** Prodávat by se měl už za dva roky

17.  11.  2017 | Vojtěch Malý | 183

30 počítačových brzd, které vám zpomalí Windows

30 počítačových brzd, které vám zpomalí Windows

Na webu najdete hromadu rad, jak zrychlit počítač a Windows. My jsme na to šli opačně a naopak jsme hledali činnosti, které ho nejvíce zpomalují. Toto je třicítka těch základních.

12.  11.  2017 | Jakub Čížek | 91

Elektronika, která nepotřebuje kabel ani baterii. Živí se rádiovým šumem

Elektronika, která nepotřebuje kabel ani baterii. Živí se rádiovým šumem

** Každá elektrická krabička má konektor pro napájení nebo baterii ** Jenže pozor, jednou by to tak nemuselo být ** Drobná elektronika se může živit rádiovými vlnami

14.  11.  2017 | Jakub Čížek | 15

Nejlepší notebooky do 10 tisíc, které si teď můžete koupit

Nejlepší notebooky do 10 tisíc, které si teď můžete koupit

** I pod hranicí desíti tisíc korun existují dobře použitelné notebooky ** Mohou plnit roli pracovního stroje i zařízení pro zábavu ** Nejlevnější použitelný notebook koupíte za pět a půl tisíce

16.  11.  2017 | Stanislav Janů | 53

Do 20 let nebude nikdo vlastnit auta, říká zkušený šéf několika automobilek

Do 20 let nebude nikdo vlastnit auta, říká zkušený šéf několika automobilek

** Bývalý šéf a expert z několika velkých automobilek se vyjádřil k budoucnosti tohoto průmyslu ** Do 20 let „nikdo“ nebude vlastnit auta ** Veškerá doprava bude řešená pomocí velkých logistických platforem

15.  11.  2017 | Karel Javůrek | 74


Aktuální číslo časopisu Computer

Otestovali jsme 5 HDR 4K televizorů

Jak natáčet video zrcadlovkou

Vytvořte si chytrou domácnost

Radíme s koupí počítačového zdroje