Jarda Jirava

Vývojář a architekt řešení postavených na technologii .net framework. Zabývám se jak vývojem webových aplikací za pomoci asp.net, tak také desktopových aplikací winform. Při návrhu řešení a samotném vývoji pak využívám dlouholetých zkušeností se zpracováním obchodní logiky a pravidel aplikací získaných z vývoje komerčních aplikací pro finanční a bankovní instituce.

Microsoft MVP

Microsoft MVP - Client App dev

Poslední příspěvky

29
Oct

Lokalizujeme asp.net aplikaci

Jistě každý zná situaci, kdy je nutné lokalizovat aplikaci a nabídnout ji uživatelům v několika jazykových mutacích. .NET framework toto řeší velice elegantně pomocí resource souborů a ResourceManagera. V asp.net 2.0 je celé řešení velice důmyslně řešeno, kdy je možnost jít ještě dále a nabízí se tak mít lokální a globální resource soubory, o tom, jak to celé funguje napsal poměrně zajímavý blogspot také Robert Haken v článku Lokalizace snadno a rychle - explicitní lokalizace. Jak už to však bývá, ne vše je tak kulaté jak se zdá.

Je to už nějaká chvíle co byl na konferenci o .net na fóru builder.cz položen dotaz ohledně možnosti lokalizace asp.net aplikací. Tenkrát jsem slíbil, že se pokusím sepsat nějaký krátký příspěvek na toto téma a zpřístupnit tak své nabyté zkušenosti také ostatním.

O co se konkrétně jedná? Autora dotazu zajímalo, zda je možné použít k lokalizaci texty, které má umístěny v databázi. Odkazů na řešení daného úkolu se našlo hnedka několik, ale většinou se jednalo o takové řešení, které nebylo elegantní (alespoň mě se nezdálo). Převážně se taková řešení opírala o skutečnost, že je nutné explicitně provést lokalizaci daného textu z codebehind stránky tj. vytvořit si nějaký vlastní DbResourceManager a pomocí metod GetString provádět lokalizaci jednotlivých textů. Přitom je velice elegantní a dostupné řešení v asp.net 2.0, a to použítí meta značek a nebo alespoň použití explicitní lokalizace tedy uvedení této konstrukce.

property="<%$ Resources: LokalizovanyText %>"

Jaká je tedy možnost lokalizace v případě, že nechci používat resource soubory? Mám já, jako vývojář, nějakou možnost si říci, že všechny texty budou uloženy třeba v databázi a odsud se budou načítat? A to ještě pokud možno s co nejmenším úsilým, které k lokalizaci bude nutné udělat? Nebude nutné se uchýlit k nějakému vlastnímu formátu řešení lokalizace, byť by bylo sebelépe navrženo, a upustit tak od modelu, který je v současné chvíli podporován v asp.net 2.0? Nesetkám se zde s podobným problémem, který nastavá u celkové konfigurace aplikace, kdy je možné používat ConfigurationManager pouze ve spojitosti s .config souborem a přitom je občas vhodné mít konfiguraci uloženu i jinde

Na poslední otázky je však v souvislosti s lokalizací možné odpovědět, nikoliv. Tím řešením je napsat si vlastní ResourceProviderFactory a implementovat několik rozhraní případně dědit z tříd již existujících. To celé potom spojit v jeden funkční celek pomocí konfiguračního souboru web.config v jeho sekci globalization a to atributem resourceProviderFactoryType.

O tom, jak si napsat takový jednoduchý ResourceProvider, kterým je možné lokalizovat asp.net aplikace a vesměs pouze přepínat pomocí konfigurace mezi jednotlivými možnostmi, se rozepíšu příště.

14
Dec

Úvodní pohled na role provider

Jistě sami naleznete několik scénářů ve vlastní aplikaci, kdy zjistíte, že je dobré znát právě přihlášeného uživatele. Ať už je to z důvodu, že mu chcete udělat radost a přivítat jej oslovením, nabídnout mu něco navíc, co nepřihlášenému nemůžete, nebo mu jenom ušetřit práci s vyplňováním informací ve formuláři (příkladem mohou být e-shopy). Z toho důvodu je k dispozici Membership provider. Na druhé straně ovšem stojí otázka bezpečnosti citlivých dat. Snad každá lepší aplikace má svoje administrační rozhraní, ke kterému by měli mít přístup pouze oprávnění uživatelé a v takových situacích nám nebude stačit vědět pouze to, že daný uživatel je přihlášen. Budeme chtít uživatele přiřazovat do jednotlivých rolí, abychom jim zpřístupnili pouze tu "správnou" část aplikace, ve které má smysl, aby se pohybovali a činili nějaké úkony.

K zajištění tohoto úkolu nám poslouží právě Role provider. Ten umožňuje k založeným uživatelům přiřazovat role. V tomto ohledu se fantazii meze nekladou, a tak jeden uživatel, může být členem hned několika rolí a samozřejmě záleží jen na našem uvážení, zda potom takový uživatel bude mít dostatečná práva pro činnosti, které má vykonávat, nebo naopak nebude mít práv příliš mnoho. A to hlavně z toho důvodu, že podle těchto rolí je řízen přístup k jednotlivým zdrojům (stránkám, prvkům) naší aplikace.

Role uživatelů

Přiřazování

Když jsem se minule zmiňoval o velké podpoře v oblasti připravených uživatelským prvků, které postačovalo umístit na stránku a téměř vše bylo hotovo, v případě role providera je tomu naopak. Pro přiřazení role uživatelům musíme sáhnout do vlastních řad a prvky si vytvořit sami, případně můžeme využít možností již zmíněného nástroje Web site administration tool.

Ověřování

K práci s rolemi používáme, stejně jako u ostatních providerů, statickou třídu, tentokráte pojmenovanou Roles. K ověřování příslušnosti uživatele do role, můžeme použít ovšem hned tři možnosti, první z nich je metoda Roles.IsUserInRole(string role), která vezme aktuálně přihlášeného uživatele a ověří jej proti předané roli. Druhou možností je opět stejně nazvaná metoda, ale se dvěma parametry Roles.IsUserInRole(string username, string role) umožňující ověřit příslušnost jakéhokoli uživatele, zda je členem dané role. Poslední možností je použít vlastnost User (objektu Page nebo HttpContextu) a metodu, jak jinak, opět nazvanou IsUserInRole.

Na tomto místě je dobré se zmínit o tom, že kontrolovat přístup ke zdrojům nemusíme dělat jen my, ale tuto úlohu za nás plní i některé uživatelské prvky. Jako dobrý příklad bych mohl zmínit TreeView kontrol napojený na Site map provider s povolenou vlastností securitytrimmingenabled. Pokud je pak u položky menu vyplněna vlastnost Roles, porovnává se tato s rolemi přiřazenými pro uživatele a v případě, že daný uživatel nemá oprávnění na danou položku, tato se mu nezobrazí.

Nastavujeme oprávnění přístupu

V okamžiku, kdy jsem se v minulém odstavci zmiňoval o oprávněních uvědomil jsem si, že vlastně ještě nevíme, jak takové oprávnění nastavit. Samozřejmě to není nic těžkého a jedná se o jednoduchý zásah do konfiguračního souboru aplikace. V části pojmenované // můžeme specifikovat uživatele nebo role, které mají přístup do které části aplikace a do kterých jim má být přístup odmítnut. Jak se jistě dozvíte i odjinud, konfigurační soubor může být umístěn v každé složce a může obsahovat tyto informace, případně můžete mít pouze jeden konfigurační soubor a specifikovat element location s atributem path, který určí příslušný soubor nebo adresář, pro který budou platit nastavení. Níže se nachází část konfiguračního souboru, který umožní přístup anonymním uživatelům k souboru logon.aspx, aby se mohli přihlásit k aplikaci.


   
      
         
            
         
      
   

V závislosti na tom, jak máme strukturován web, tak můžeme povolovat a zakazovat přístup uživatelům, ale spíše předpokládám, že se budeme snažit nastavovat oprávnění právě skupinám. Tudíž elementy, které nás budou zajímat jsou

Nebo můžeme využít zástupných znaků * pro všechny uživatel a ? pro anonymní uživatele.

bezpečná aplikace

Právě jsme si dokázali, že zabezpečit aplikaci a nastavit oprávnění pro jednotlivé uživatele a role nemusí být vůbec náročné. Samozřejmě je nutné zminit, že to již bylo možné použít v .NETu 1.0 nebo 1.1, ovšem nikoli s takovou variabilitou. Neboť nesmíme zapomínat na to, co je hlavním důvodem a účelem pro použití provider patternu a tou je nezávislost, možnost změny. Také z toho důvodu je nutné připomenout, ža jako výchozí provider je nastaven AspNetSqlProfileProvider a pokud jej chceme změnit za jiný, můžeme tak učinit v konfiguračním souboru. Jako mávnutím kouzelným proutkem tak můžeme přebírat nastavení z Active directory nebo například xml souboru.

Publikováno pod: asp.net providers
13
Dec

Úvodní pohled na membership provider

Pomalu se dostáváme k providerům, které můžeme sice použít samostatně, ale při jejich použít je budeme většinou využívat společně. Jedná se o Membership, který si představíme nyní, tak také Role a Profile provider, na které přijde řada v nejbližší možné době.

Membership provider použijeme v okamžiku, kdy chceme spravovat uživatele naší aplikace, pokud chceme zajistit vytvoření uživatelského účtu, změnu hesla nebo jeho obnovení, můžeme si vynutit použití kontrolní otázky. Dále pak slouží k validaci uživatelského jména a přístupového hesla uživatele, který přistupuje do aplikace, a nesmíme zapomenout na to, že k danému uživateli můžeme sledovat další dodatečné informace jako je email adresa a další.

Jak už jsem se zmínil v prvním odstavci, membership provider budeme většinou používat ve spojitosti s role providerem. Neboť membership umožňuje pouze authentikaci uživatele, nikoli však už jeho autorizaci, tj. zajištění oprávnění ke zdrojům. Na toto nesmíme zapomenout při vytváření naší aplikace.

Co se týká vestavěné podpory v .NET Frameworku, tak ta obsahuje pouze dvě implementaci membership provideru a to Active directory a SqlMembership provider. Nesmíme ovšem zapomenout na to, že pro to, abychom mohli založit a spravovat uživatele, stejně jako dovolit uživatelům se přihlásit k naší aplikaci potřebujeme nějaké vizuální prvky, a těch máme k dispozici hned několik.

Uživatelské prvky využívající membership provider

  • Login
  • - poskytuje základní prvky pro přihlášení uživatele, jako je uživatelské jméno a heslo, plus můžeme přidat zaškrtávací pole pro zapamatování (trvalé přihlášení) si uživatele
  • LoginView
  • - představuje jednoduchý prvek, který má dva stavy, které zobrazuje na základě toho, zda je uživatel přihlášen, nebo naší aplikaci používá anonymní uživatel
  • LoginStatus
  • - zobrazuje stav, ve kterém je uživatel a nabízí dvě možnosti, přihlásit nebo odhlásit
  • LoginName
  • - zobrazuje jméno přihlášeného uživatele
  • PasswordRecovery
  • - je prvek, který umožňuje uživateli zaslat, nebo spíše vygenerovat a odeslat na email nové heslo pro přístup do aplikace
  • CreateUserWizard
  • - je komplexnější prvek, který umožní založení nového uživatele. Samozřejmě si tento prvek můžete přizpůsobit aby odpovídal vzhledu vaší aplikace
  • ChangePassword
  • - umožňuje uživateli změnit si heslo.

Velice zajímavý prvek je CreateUserWizard, který umožňuje založit nového uživatele pro naši aplikaci. Tento prvek může být velice snadno upravitelný a můžeme jej rozšířit o další možnosti. Za tímto účelem můžeme definovat tento prvek jako průvodce vytvořením uživatelského účtu a přidat si kroky, kterými musí uživatel projít předtím, než jeho účet bude vytvořen. Zbývá nám ovšem ještě základní pohled na kterém je zobrazeno několik vstupních textových polí, pro které nenajdeme vlastnosti, jak je skrýt nebo jakkoli jinak nastavit. To nás ovšem nesmí zmást, protože několik vlastností je součástí Membership provideru a některé implementace nemusí mít dané vlastnosti funkční. Proto není možné je nastavovat na kontrolu, ale jejich nastavení se přebírá z právě aktivního provideru. Patří mezi ně vlastnosti requiresQuestionAndAnswer, minRequiredPasswordLength, minRequiredNonalphanumericCharacters nebo passwordStrengthRegularExpression. Obzvláště si dejte pozor na dvě prostřední, které mohou uživateli z(ne)příjemnit jeho přihlašování.

Určitě nastanou také situace, kdy budeme chtít vědět o uživateli více než jen jeho uživatelské jméno, a tak nás bude zajímat třída MembershipUser. Jakmile dostaneme data pomocí providera, např. pomocí statické metody Membership.GetUser(string userName), můžeme tyto informace zobrazit, nebo s nimi jinak naložit v naší aplikaci.

Web Site Administration Tool

Bez velké námahy můžeme vložením několika prvků na stránku zajistit celkem komplexní funkcionalitu správy uživatelů, ovšem co v situaci, kdy jsme administrátorem a potřebujeme nastavovat nejen uživatele, ale i jejich přiřazování do rolí a vlastně nejen do rolí, ale i správu dalších vlastností, které je možné konfigurovat? Teď si jistě říkáte, ale co s tím, teď jsme založili uživatele, role mě zatím nezajímají a o ostatních nastaveních, to není předmět tohoto webu. Ale přeci jen, Web site administration tool je mocným nástrojem, který nám umožní nastavit vše potřebné na jednom místě a to ať už se jedná o správu uživatelů, správu rolí a přístup k jednotlivým složkám webu, konfigurační hodnoty AppSettings, nastavení použitých providerů nebo nastavení SMTP serveru. Stejně tak jako nám dovolí nastavit trasování aplikace a chybové stránky nebo uvést aplikaci do stavu OffLine.

Jak je z popisu poznat, tento nástroj dává k dispozici komplexní nastavení aplikace a Vám nezbývá nic jiného, než k němu přistoupit a začít konfigurovat a hrát si s nastavením.

Co dodat

Uživatele umíme založit aniž bychom napsali řádek kódu, dokážeme uživateli nabídnout přihlašovací dialog a zobrazit mu jeho status, zda je přihlášen, nebo se může odhlásit. Ale metod, které můžeme použít se statickou třídou Membership je více a asi nemá význam, je zde po jedné rozebírat. Pokud budete chtít vědět více, určitě napiště do komentáře.

Jedny z mála řádků, které budeme muset dopsat do našeho kódu, jsou řádky pro autentikaci uživatele a jeho přihlášení pomocí Login prvku. A kolik je těch řádků? Samozřejmě co nejmíň, musíme se přeci soustředit na jiné věci, které má naše aplikace splňovat a ne si hrát s nastavováním uživatelů. Takže, tady jsou ty potřebné řádky (login představuje Login kontrol):

if (Membership.ValidateUser(login.UserName, login.Password))
			FormsAuthentication.RedirectFromLoginPage(login.UserName, login.RememberMeSet);
Publikováno pod: asp.net providers
13
Dec

Web events - část 3.

Konkrétní příklad - web event

Jak už jsem naznačil v minulém článku, v tomto pokračování se budu věnovat konkrétnímu příkladu, který by měl objasnit použití a možnosti, které nám přináší healt monitoring.

Určitě i Vás, případně Vaše klienty, zajímají odpovědi na otázky, jak je využívána aplikace, nejsou na ní prováděny neoprávněné operace, a jistě spousta dalších, které by zaplnily velkou část tohoto příspěvku. Sám jsem byl ovšem velice zvědavý na to, jakým způsobem je tato aplikace využívána a jakým způsobem se po ní pohybujete. Stejně tak jistě i Váš klient tyto informace ocení.

Tvorba WebRequestAdvEvent

Pro sledování Vašeho pohybu na těchto stránkách jsem původně chtěl využít již vestavěný WebRequestEvent. Ovšem zde jsem narazil, a to hnedka na dvě nepříjemné věci. Jedna mě zamrzela poměrně hodně, ta druhá o něco méně, protože jsem věděl, jak jí odstranit. Pravda, nakonec jsem tím odstranil obě, ale budu rád, když mi zanecháte Vaše zkušenosti, a případně postup jak jste odstranili první vadu.

WebRequestEvent

Nejdříve jsem si myslel, že použiju tuto třídu ke sledování pohybu na stránkách, ovšem již při testování jsem narazil. Přestože jsem vše nakonfiguroval, a troufám si tvrdit že správně, události této třídy se ne a ne logovat. Prošel jsem několik možných konfigurací, ale ani s jednou se mi nepovedlo úspěšně zalogovat jedinou událost, pomocí mého oblíbeného vyhledávače jsem se snažil o tomto problému najít více informací, ale ani tady jsem příliš neuspěl. Jediné co jsem zjistil, že už v Beta 1 byl tento problém, bohužel bez odpovědi. Tudíž logování informací z této třídy odpadlo, ono stejně bych tento přístup zavrhl, protože informace, které obsahuje a shromažďuje, ne úplně odpovídali tomu, co jsem chtěl sledovat já navíc.

Vlastní trída poděděná z WebRequestEvent

Po zjištění výše uvedeného jsem se rozhodl implementovat vlastní třídu, která bude rozšiřovat shromažďované informace a navíc půjde logovat. Tudíž jsem vytvořil vlastní třídu a přepsal jsem metodu public override void FormatCustomEventDetails(WebEventFormatter formatter). Do této metody jsem doplnil následující část kódu, která zjišťuje informace o prohlížeči, který uživatel použil a také, ze které stránky se na ty mé dostal.

System.Web.HttpContext ctx = System.Web.HttpContext.Current;
formatter.IndentationLevel++;
if (ctx != null) {
	formatter.AppendLine(string.Format("User agent : {0}", ctx.Request.UserAgent));
	if (!string.IsNullOrEmpty(ctx.Request.UrlReferrer))
		formatter.AppendLine(string.Format("Referrer : {0}", ctx.Request.UrlReferrer.ToString()));
} else {
	formatter.AppendLine("You use this web event outside of web application. No data are provided.");
}
formatter.IndentationLevel--;

Zde si dovolím upozornit, že všechny uživatelské události, by měli mít hodnotu eventCode větší než WebEventCodes.WebExtendedBase

Měl jsem vytvořenou vlastní třídu pro sledování událostí, teď jí ještě umístit na správné místo ve stránkách a nastavit konfigurační soubor. A měl jsem hotovo, stačilo pár řádků kódu a vím o Vás všechno :-).

Používáme WebRequestAdvEvent

Proto, abych mohl použít logování vlastních událostí, musí se tyto události někde generovat. Tato aplikace využívá možností MasterPage, takže umístění vyvolání události bylo snadné, přímo do metody Page_Load a to následovně.

WebRequestAdvEvent evt = new WebRequestAdvEvent(this);
evt.Raise();

Události se nám vyvolávají a jediné co zbývalo, je nastavit jejich logování pomocí konfiguračního souboru. Není přeci nic snažšího, protože z první a druhé části víme, jak na to.

Zhodnocení místo závěru

Osobně si myslím, že používání událostí tímto způsobem je poměrně užitečná věc, která nám ušetří něco málo práce. Jen bych měl několik poznámek ke způsobu, jakým dochází k zápisu informací. V době, kdy je prosazován formát xml, by aspoň mohl existovat přepínač, který by umožnil rozšířené hodnoty logovat do tohoto formátu. Přeci jen mít data nestrukturovaná znamená jejich horší zpracování. Rozumím, že při použití některých providerů, není tento formát úplně optimální, ale přeci jen, jedná se převážně o systémové informace, které uvidí zkušení uživatelé a ti si s XML už ví rady.

A nakonec prosba na Vás, pokud víte, jak zprovoznit logování událostí pocházejících ze třídy WebRequestEvent, budu rád, když napíšete své postřehy do komentářů. Díky

Publikováno pod: asp.net providers
9
Dec

Web events - část 2.

Tím vše nekončí - healthMonitoring ve web.config

Pokud si vezmeme ostatní providery, většinou tímto krokem končíme a jediné co musíme udělat, je korektně nastavit konfigurační soubor. Toto však až tak neplatí pro web events, i když vše je relativní a toho nastavování budeme moci provést o něco více, než v případě registrování ostatních provider patternů.

V konfiguračním souboru tak pod elementem nedefinujeme pouze podsekci providers, ale také říkáme, které události chceme sledovat, jakým způsobem budou sledovány, jaká pro ně existují pravidla a jak se seskupují, případně jaký chceme používat způsob cachování (bufferu). Jednotlivé sekce zkusím popsat

bufferModes

V této sekci definujeme možnosti bufferingu zvoleného providera, který zachytává a dále publikuje události. Nastavovat tímto způsobem můžeme providery, které jsou odvozeny od BufferedWebEventProvider. Tím, že zabezpečíme buffering, zvýšíme tak výkonnost naší aplikace, neboť nebudeme zapisovat okamžitě vzniklé události, ale tyto budou pozdrženy před jejich zápisem pomocí příslušného provideru, zároveň můžeme rozlišit mezi kritickými (urgentními) a standardními událostmi.

Ukázka


	

profiles

Přidáním této podsekce máme možnost ovlivnit profil zaznamenávání událostí. Nastavením vlastností tohoto profilu určíme, jaký je minimální počet instancí události, po kterých se má tato zalogovat, případně také její maximální počet (nic nám nebrání nastavit hodnotu Infinite), jakož i minimální časový interval mezi dvěma shodnými událostmi, které se mají logovat. Těchto profilů využijeme v okamžiku, kdy se dostáváme do kritických situací a potřebujeme kontrolovat počet zapisovaných dat a zátěž na systém.

Ukázka jaké je výchozí nastavení pro sekci profiles:


	
	

eventMappings

Předpokládám, že tato sekce nás bude zajímat více než ostatní, zejména v okamžiku, kdy budeme tvořit vlastní události. V této sekci můžeme přidávat vlastní seskupování událostí, nebo přidávat vlastní události do již předpřipravených skupin. Tyto připravené skupiny jsou dvě All Events a All Audits, které se pak ještě rozpadají na <All Errors a All Failure. Nic nám ovšem nebrání v tom, abychom si definovali vlastní skupiny a tyto skupiny si nechali zpracovávat vlastním providerem.

Ukázka se zařazením vlastní události do nové skupiny My Errors


	        

rules

Poslední z podsekcí, kterými můžeme nastovovat chování a zpracovávání událostí. Pomocí tohoto nastavení definujeme a vlastně tak seskupíme všechny výše naspecifikované hodnoty. Zapsáním pravidel tak říkáme, jakým providerem budou zpracovány jaké události a jakým způsobem profilem se tak bude dít.

Ani pro poslední podsekci nesmí chybět ukázka. Kdy si pro naši fiktivní událost definovanou v eventMapping zvolíme jeden ze standardních providerů a nastavíme jí critický profil.


  
  

Shrnutí konfigurace

Jak je vidět, můžeme díky konfiguraci sledovat a nastavovat nepřeberné množství vlastností a ovlivňovat tak způsob, kterým budeme sledovat naši aplikaci. Pokud nám stačí sledovat pouze frameworkem generované události, postačí nám k tomu jednoduché nastavení a povolení v konfiguračním souboru. Potom se použijí výchozí hodnoty a události vyskytující se ve skupinách All Errors a Failure Audits se budou zapisovat do Event logu.

Příště si na příkladu ukážeme, jak vytvořit vlastní událost a sledovat jí pomocí vlastního provideru.

Publikováno pod: asp.net providers
9
Dec

Web events - část 1.

Pro dnešní příspěvek jsem si vybral jednu ze zajímavých, ale podle mého názoru, lehce opomíjených oblastí, jsou to Web events neboli také Health Monitoring. Ty slouží k monitorování webových aplikací a mohou tak pomoci administrátorům a vývojářům pomoci s výkonností aplikace a její sledování, rychlé diagnostice aplikace, ve které dochází k chybám a v neposlední řadě i sledování průběhu životního cyklu stránky.

Které všechny události můžeme sledovat

Samozřejmě že můžeme definovat i vlastní třídy, které budou sledovat události, ale aby nám vývojáři od Microsoftu ušetřili spoustu práce, máme ihned k dispozici několik tříd pro sledování událostí. Vrhneme se na jejich prozkoumání s chutí.

  • WebBaseEvent - základní třída pro všechny eventy, která obsahuje povinné vlastnosti, které musí mít každý web event. Mezi tyto vlastnosti patří, kód události, detailní kód události, datum a čas vzniku události, sekvenční číslo, text událost a detaily o události.
  • WebManagementEvent - je základní třídou pro události týkající se správy událostí, životního cyklu aplikace, zpracování požadavků a chyb, stejně jako auditních událostí.
  • WebHeartbeatEvent - je třída pro zpracování událostí, které jsou generovány v pravidelných časových intervalech pro zachycení stavových informací aplikace.
  • WebAuditEvent - základní třída pro evidování bezpečnostních událostí, používá se pro audit při zpracování autorizace, a to jak provedených tak i chybných. A nejen týkající se bezpečnosti, ale i kryptování a dalších ...
  • WebRequestEvent - základní třída pro informace zpracovávající události o požadavcích [requestech].
  • WebBaseErrorEvent - jak už název napovídá, jedná se o základní třídu pro všechny události týkající se chyb.

Dobrá, známe tedy třídy, které budeme moci používat, ale jakým způsobem je použít a jak to vše zakomponovat do našich stránek, aby to přineslo kýžený efekt. Po jakých informacích se nejspíše budeme dále shánět, jsou informace typu, kde se všechny ty informace budou shromažďovat, jak se k nim dostanu a co všechno budu muset dopsat. Nenapadá Vás to také? Mě ano a mám potěšující informaci, těch řádků, které se musí napsat není tolik, možná i méně něž kolik jsem jich již sepsal v tomto příspěvku. ;-) Ale zpátky od laškování k suchému konstatování.

Můžeme si vybrat hnedka z několika nabízených providerů, které zapisují informace o událostech do WMI, Event logu, posílají email používají SQL Server a další, případně si můžeme napsat vlastní úložiště ... po čem jsem viděl velký ohlas byl XmlWebEventProvider.

Publikováno pod: asp.net providers
7
Dec

Vlastní .net provider - část 2.

Bázová třída pro RandomService

Tak abychom mohli vytvořit a dále i volat ze statické třídy RandomService konkrétní implementace, musíme ještě vytvořit abstraktní třídu, jejíž metody a případně vlastnosti budou poté implementovat konkrétní instance, které budeme tvořit, případně je vytvoří třetí strana.

Tato bázová třída má stejné metody jako statická třída, ovšem s tím rozdílem, že nejsou definovány jako statické, ale jako abstraktní. Tudíž interface takové třídy bude vypadat

public abstract class RandomBaseProvider: ProviderBase {
	public abstract int Random();
	public abstract int Random(int lowerBound, int upperBound);
	public abstract int Random(int lowerBound, int upperBound, int inicialization);
}
Samozřejmě nesmíme zapomenout na to, že tato třída musí být poděděna z ProviderBase, jinak by celé naše snažení nebylo na správné cestě a setkali bychom se s několika problémy.

Pojďme ale dále, máme vytvořeno rozhraní, výchozí třídy, které definuje přístup jakým způsobem budou volány konkrétní implementace z aplikace. Co nám tedy zbývá? Vedle napsání právě oné vlastní implementace ještě musíme zařídit, že budeme moci definovat a konfigurovat providery z konfiguračního souboru aplikace.
Je nutné říci, že abstraktní třída nemusí mít přesně stejný interface jako statická třída.

Konfigurační sekce pro vlastní provider

Již se blížíme k závěry celého našeho snažení, tato část je skutečně už jen tou pověstnou třešinkou na dortu. Zbývá nám totiž dodefinovat celkem dvě vlastnoti pro naši konfigurační třídu. Asi nemá význam se tady příliš rozepisovat, když pohled na kód řekne víc, než tisíce slov. Tady to je:

	public class RandomServiceSection: ConfigurationSection {
		[ConfigurationProperty("providers")]
		public ProviderSettingsCollection Providers {
			get {
				return (ProviderSettingsCollection)base["providers"];
			}
		}

		[StringValidator(MinLength = 1)]
		[ConfigurationProperty("defaultProvider",
				DefaultValue = "RandomProvider")]
		public string DefaultProvider {
			get {
				return (string)base["defaultProvider"];
			}
			set {
				base["defaultProvider"] = value;
			}
		}
	}

A máme vše připraveno.

Vlastně, ještě zbývá malá drobnost, samotná registrace do konfiguračního souboru a definice providerů. Toto již určitě znáte i z předchozích verzí, kdy jste si chtěli registrovat vlastní sekce v konfiguračním souboru. Tudíž nás budou v tuto chvíli zajímat oddíly configSections a především její podsekce kam přidáme definici našeho RandomServiceSection typu.

Poté už jen zaregistrovanou sekci uvedeme v život její definicí v sekci a to takto:

	
		
		
	

V této ukázce jsem zaregistroval dva providery, jeden generuje náhodná čísla pomocí třídy Random, ten druhý pak má seznam náhodných čísel uložených v databázi a vrací je postupně. Pro tento provider platí, že bude inicializován zároveń s předaným názvem connection stringu.

Závěr

Tvorba vlastního providera není příliš složitá, na co je důležité dát si pozor, aby rozhraní, které bude takový provider definovat byl pokud možno co nejvíce univerzální a nebyly do něj zahrnuty specifické - implementační - záležitosti, které by způsobily, že napíšeme pouze jednu implementaci takového provideru. Smyslem našeho snažení by měla být co největší nezávislost a možnost volby, jakým způsobem budeme implementovat požadovanou funkčnost.

Publikováno pod: asp.net providers
7
Dec

Self promotion

Všechno dnes stojí na reklamě, důvtipném a neotřelém marketingu, propagaci. Tak si říkám, když už si píšu pár poznámek a něco málo vím, mohl bych toho využít a udělat si vlastní promotion.

http://providers.aspweb.cz

Tak jako několik desítek ostatních i já jsem se přihlásil do soutěže LCD za web se stránkami věnovanými Provider pattern. Snažím se na nich přiblížit popisem a příklady fungování i používání tohoto návrhového vzoru v prostředí .NET 2.0. Sám jsem tento návrhový vzor začal používat před nějakým tím časem, kdy byl k dispozici pouze .NET 1.1 a je pravda, že je dostatek situací, ve kterých se dá tohoto vzoru použít. Proto jsem si říkal, že nebude od věci zpřístupnit své znalosti i ostatním českým vývojářům. A doufat, že se mi třeba odvděčí posláním svého hlasu pod číslem 1312.

Jádrem celého webu je pak jednoduchý systém, založený na, jak jinak, provider patternu. Vlastní implementaci ContentProvideru, která umožňuje zobrazování příspěvků, jejich přidávání, stejně tak jako reakci na příspěvky. Zdrojové kódy pro tento provider budou k dispozici v blízké době. Přeci jen mé rozhodnutí přišlo takříkajíc na poslední chvíli a nerad bych dával v plén něco neodzkoušeného a neprověřeného více návštěvami.

Přeci jen jsou tyto stránky především informační, a nesnažím se myslet jen na sebe, dalšími kdo se přihlásil do soutěže byl i Tomáš Petříček, který postavil pěknou aplikaci. A přehled zajímavých řešení postavených na ASP.NET 2.0 přinesl B. Stanik T. v upoutávce Zajímavé projekty v soutěži LCDZAWEB.CZ (škoda, že jsem se do nich nevešel, že by to skutečně nikomu nic nepřineslo???).

Jenom malý povzdych na okraj

Škoda že můj poskytovatel webového prostoru zatím neumožňuje provozovat ASP.NET 2.0 stránky, určitě by to stálo za to. Navíc bych tak mohl využít a odzkoušet ten malý publikační systémek i zde.

Publikováno pod: asp.net providers , personal
7
Dec

Vlastní .net provider - část 1.

Pojďme se přesunout na chvíli od vestavěných providerů k těm, které si vytvoříme podle obrazu svého. Jednotlivé kroky si předvedeme na jednoduchém příkladu.

Něco málo úvodem o ProviderBase třídě

ProviderBase třída je výchozí třídou, v případě, že chceme psát vlastní providery, stejně tak jako od ní dědí všechny dostupně providery v .NET Frameworku 2.0. Tato třída je tedy novou třídou v novém frameworku, vyznačuje se svojí jednoduchostí a obsahuje pouze minimum (jednu) metod s minimem vlastností (slovy dvě).

Nejdříve se podíváme na metodu virtual Initialize(string name, NameValueCollection config). Tato metoda nám umožňuje napsat vlastní inicializaci pro provider a to díky kolekci config ve které najdeme všechny parametry, které jsou definovány u definice providera v konfiguračním souboru. Tak jsme například získali odkaz na connectionString u prvního MsSqlSiteMapProvidera. Je nutné zdůraznit, že tato metoda, se volá pouze jedenkrát za životní cyklus a v případě vícenásobné inicializace je vyvolána výjimka InvalidOperationException. Pro všechny providery pak platí, že běhové prostředí .NETu zajišťuje (samozřejmě v případě správného použití), aby k instancování konkrétní implementace ProviderBase docházelo pouze v jednom Threadu.

Definujeme Interface našeho providera

Nyní již víme, jak budeme moci napsat vlastní implementaci pro vlastní provider, co je ovšem důležité, definovat rozhraní pro komunikaci, tak abychom mohli skutečně využít všech výhod, které nam tento návrhový vzor přináší. Pro tento účel definujeme dvě třídy.

Statická třída pro našeho providera

Statická třída představuje obecný interface, pomocí kterého budeme přistupovat ke konkrétní implementaci providera. Jak už jsem uvedl, jedná se o statickou třídu - taktéž novinku v .NET 2.0 - jejíž všechny metody a vlastnosti jsou statické.

Důležitou součástí takové třídy je inicializace providerů, kteří jsou definováni v konfiguračním souboru aplikace. Toto můžeme zajistit následující částí kódu (metodou)

private static void Initialize() {
1. if (provider == null) {
2. 	lock (lockObject) {
3. 		if (provider == null) {
4. 			RandomServiceSection section = (RandomServiceSection)WebConfigurationManager.GetSection("system.web/randomService");
5. 			providers = new RandomProviderCollection();
6. 			ProvidersHelper.InstantiateProviders(section.Providers, providers,	typeof(RandomProviderBase));
7. 			provider = providers[section.DefaultProvider];
8. 			if (provider == null)
9. 				throw new ProviderException("Unable to load default RandomProviderBase");
10.		}
11.	}
12.}
}
Projděme si jednotlivé řádky:
1.-3. kontrolujeme, zda ještě není instancován žádný provider - pro znalé představují řádky 1-3 tzv. DoubleCheckedSingleton design pattern.
4. načteme si příslušně označenou sekci z konfiguračního souboru, která obsahuje seznam dostupných providerů.
5. instancování kolekce providerů, kterou budeme používat 6. volání této konstrukce nám zajistí nainstancování všech dostupných providerů - zároveň volá metodu Initialize 7. přiřazení výchozího providera, se kterým se bude momentálně pracovat 8.-9. ošetření případu, kdy neexistuje výchozí provider

Po inicializaci providera už nám zbývá jenom definovat rozhraní, pro tento vzorový případ jsem definoval pouze jednoduché rozhraní a to metodami

  • public static int Random()
  • public static int Random(int lowerBound, int upperBound)
  • public static int Random(int lowerBound, int upperBound, int inicialization)
, které budou vracet náhodné číslo. Vím, není to úplně originální případ, doufám však, že pro demonstraci toto bude dostačovat. Obzvláště v případech, kdy budeme chtít zajistit výpočet náhodného čísla různými algoritmy.
Každá tato metoda volá příslušné metody providera následujícím způsobem
public static int Random() {
  RandomService.Initialize();
	return RandomService.Provider.Random();
}

Máme tedy definováno rozhraní v naší tříde RandomService, nyní vytvoříme druhou třídu, která bude předkem pro naše konkrétní implementace.

Publikováno pod: asp.net providers
5
Dec

Přehled zdrojů pro asp.net providery

Tento příspěvek měl být prvním, ovšem jak už to tak bývá, ne vše se podaří jak má a tak se na první přehled zdrojů podívám až nyní.

Pro začátek jsem vybral zdroje, které pocházejí přímo od Microsoftu. Pojďme se na ně podívat. Asi prvním bohatým zdrojem, popisujícím veškeré dostupné Providery je ASP.NET 2.0 Provider Model: Introduction to the Provider Model. Stránka, kde doporučuji se zastavit a přečíst při svém prvním seznamování se. (Teda pokud jako první nenavštívíte tyto stránky :-).) Když už jsem se v prvním příspěvku zmínil o SiteMap provideru, určitě Vás bude zajímat i jeho implementace v podání Jeff Prosise. Ano vzal jsem si inspiraci a upravil několik věcí, které se mi na tomto provideru nelíbili.

Dále určitě stojí za pozornost dva články od Rob Howard Provider Model Design Pattern and Specification, Part 1 a Provider Design Pattern, Part 2, jež jsou poněkud staršího data, přesto stále aktuální, a já v nich měl inspiraci již pro projekty postavené na .NET 1.1.

Ale vrátím se od pouhého čtení k něčemu, co některým (snad skutečně jen výjimkám) udělá radost. Jsou to Sample Access Providers Starter Kit implementace pro Membership, Role Manager, Profile a Web Parts personalization s využitím Microsoft Access databáze. Dle mého názoru je toto pouze okrajové a nouzové řešení, neboť bych raději použil SQL Server 2005 Express Edition.

A když už jsem u toho kódu, který se dá použít, i když ne tak úplně souvisí s provider patterny v ASP.NET 2.0, nedá mi to abych je nezmínil. Jistě si někteří z Vás oblíbili Enterprise Library. Tato knihovna se již blíží do finálního release i pro .NET Framework 2.0 a usnadní nám práci díky těmto aplikačním blokům:

  • Caching Application Block
  • Cryptography Application Block
  • Logging & Instrumentation Application Block
  • Exception Handling Application Block
  • Security Application Block
  • Data Access Application Block
  • Configuration Application Block

Toť pro dnešek vše, další informace budou v průběhu zítřejšího dne ... vzhledem k pracovnímu vytížení, spíše večera.

Publikováno pod: asp.net providers
4
Dec

MsSqlSiteMapProvider

Součástí instalace ASP.NET 2.0 je několik providerů. Tyto se dělí do několika oblastí, pro které zprostředkovávají rozhraní. Mezi ně patří i rozhraní pro mapu webu, neboli SiteMap Provider. Ovšem, když se podíváte důkladněji po tomto provideru, zjistíte, že co nabízí ve své základní instalaci, je pouze XmlSiteMapProvider.

XmlSiteMapProvider je vhodný v okamžiku, kdy hodláte vytvořit mapu webu pomocí xml souboru. Ovšem jsou situace, kdy toto není plně vhodné. Já osobně dávám přednost raději SQL databázi, ve které je definována struktura stránek. A tak nezbývá než napsat nového providera, a tohoto začlenit do svého projektu.

Začínáme vytvářet vlastní provider - analýza

Celý princip provider patternu je důkladně popsán na těchto stránkách. A důkladněji se mu budu věnovat v dalším příspěvku. Důležité je vědět, že pro náš SiteMap provider můžeme vycházet ze dvou abstraktních výchozích tříd. První z nich SiteMapProvider je skutečnou výchozí třídou, ze které můžeme odvozovat vlastní providery. Ovšem, pokud nechceme psát příliš mnoho kódu, a který vývojář by tomu tak chtěl, můžeme použít druhou abstraktní třídu StaticSiteMapProvider. Tato, také abstraktní, třída implementuje několik metod, které bychom museli stejně napsat a usnadňuje nám tedy množství práce. Zároveň z této třídy vychází také náš MsSqlSiteMapProvider.

Dostáváme se k vlastnímu provideru

Vlastní provider je pak už jenom implementováním několika abstraktních metod. A navržením datové struktury tabulky, ve které budou obsaženy informace o struktuře webu.

Pro návrh databázové tabulky si vezmeme inspiraci z atributů, které můžeme zapsat do xml souboru a rozšíříme je o několik nutných položek. Tabulka se tak bude sestávat z těchto sloupců:

  • SMID
  • - primární klíč tabulky, zároveň slouží jako atribut key objektu SiteMapNode
  • SMParentID
  • - je odkazem na nadřazenou úroveň, např. v rámci tohoto webu je na nulté úrovni název Providers na první úrovni pak seznam všech výchozích providerů.
  • NodeOrder
  • - je pořadí příslušného nodu v dané úrovni. Tento atribut slouží pouze pro seřazení struktury na výstup.
  • Title
  • - je titulek, který se zobrazí uživateli a je mapován na stejně znějící atribut.
  • Url
  • - představuje odkaz na stránku v rámci webu.
  • Description
  • - jak už název napovídá, slouží pro popis odkazu. Pokud je tento popisek vyplněn, zobrazí se jako vyskakovací nápověda po najetí na odkaz.
  • Roles
  • - tento atribut je použit v případě nastavení property atributu SecurityTrimmingEnabled na hodnotu true. A umožňuje řízení oprávnění přístupu k webu.
  • ResourceKey
  • - nebyl by to pořádný web, který by nesloužil pouze pro jednu zemi. Takže toto je možnost, jak i menu lokalizovat.
  • Obsolete
  • - a samozřejmě můj oblíbený sloupec, který používám snad ve všech tabulkách. Nikdy totiž nevíte, jestli nebudete chtít příslušný záznam "schovat" před ostatními a přitom jej ponechat v databázi.

Takže strukturu databáze máme, přejdeme k napsání vlastního provideru. Jelikož jsem se rozhodl použít za výchozí třídu StaticSiteMapProvider, mám již spoustu kódu napsánu a tak mi zbývá implementovat jen několik málo metod.

Hned první je metoda Initialize(string name, NameValueCollection config). Zde doplníme kód pro získání připojovacího řetězce pro připojení k databázi, ve které se nachází výše zmíněná tabulka, pojmenovaná [SiteMap]. Další metodou, jejíž implementaci je nutné dopsat je SiteMapNode BuildSiteMap(), vracející kořenový nod našeho webu, většinou tedy default.aspx. Tato metoda načte strukturu webu z tabulky databáze a vytvoří příslušný strom, tak jak bude zobrazen na straně klienta. A to je vlastně téměř vše co musíme napsat, abychom získali vlastní SiteMapProvider.

Používáme vlastní SiteMapProvider

Napsali jsme vlastní provider, ale jak jej použít? Je to celkem jednoduché, chvilku se budeme zabývat souborem web.config. V jeho sekci přidáme definici pro náš vlastní provider. Ta může vypadat následovně

	
		
			
		
V připadě, že jsme předtím používali například XmlSiteMapProvider na svých stránkách, máme hotovo a struktura webu se nám rázem, samozřejmě po uložení souboru, bude načítat z nového úložiště. Jestliže začínáme psát nový web, pak musíme pro zobrazení nového menu použít příslušné ovládací prvky. Ale to si nechám zase na příště.
Publikováno pod: asp.net providers