reklama

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í, Catch

3 komentáře

Nejnovější komentáře

  • Pavel Polívka 24. 11. 2007 13:57:03
    Programovou oflline verzi seriálu naleznete ke stažení na...
  • Johnny 19. 4. 2006 19:38:21
    Je to fakt super, nemuzu si stezovat...
    http://www.make4u.cz
  • Svatopluk 17. 4. 2006 8:38:39
    chtěl bych taky do dělat web stranky
reklama
Určitě si přečtěte

UPC překopli páteřní kabel. V Brně i druhý den nejede internet ani kabelovka

UPC překopli páteřní kabel. V Brně i druhý den nejede internet ani kabelovka

** V Brně byl velký výpadek služeb UPC ** Důvodem je překopnutý páteřní kabel ** V některých lokalitách služby stále nefungují

Včera | Jakub Čížek | 94

ASUS ZenBook 3 se začal prodávat v Česku. Je ve všem lepší než MacBook, ale bude to stačit?

ASUS ZenBook 3 se začal prodávat v Česku. Je ve všem lepší než MacBook, ale bude to stačit?

** Novinka od Asusu míří přímo proti MacBooku od Applu ** Nabídne daleko více výkonu za stejné peníze

2.  12.  2016 | David Polesný | 139


reklama