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

Silverlight minesweeper

Get Microsoft Silverlight

Navrhi COOL design a vyhraj zkušební let po Evropě!

Poslední příspěvky

.net technology

10
X

Odhalujeme .net - Deserializace

O deserializaci je toho možné napsat velice mnoho. Jsou však situace, kdy si člověk říká, že má vše pod kontrolou a ono ejhle, poměrně triviální věc a najednou je vývojář v rozpacích. Něco takového se mi přihodilo poměrně nedávno, kdy jsem řešil poměrně zajímavý projekt na zpracování a převod datových struktur. Zjednodušeně řečeno, takové menší SSIS.

Deserializace ze stringu

V uvedeném řešení existovalo několik malých tříd, které sloužily jako konfigurace pro jednotlivé tasky a jež měl možnost uživatel přes vizuální prostředí editovat. Hodnoty z těchto tříd potom byly serializovány a uloženy do databáze k danému tasku. To je pro tento případ nepodstatné. Co je však podstatnější, že bylo nutné zpětně tyto třídy obnovit z takto uložených řetězců a předat do aplikace. Ano, to co jsem zde popsal bylo uschováno a bylo použito vzoru Memento. Ale i ten musí být nějakým způsobem implementován.

Toto je útržek kódu pro deserializaci

XmlSerializer xs = new XmlSerializer(creationType);
StringReader reader = new StringReader(setting);
object result = xs.Deserialize(reader);

který byl použit v prvotní fázy a jenž byl funkční. Jistě namítnete, že nevidíte nic neobvyklého a že tímto způsobem také provádíte deserializaci.

Nakonec je z toho hádanka pro Vás

Teď by možná mohla následovat otázka, co je na této části kódu špatně a v jaké situaci se nedočkáme očekávaného výsledku? Pominu to, že může dojít ke změně interface serializovaného objektu, což se nestalo. Úspěšně však zapracovalo interní testování.

Znáte tedy odpověď? Buďte prvním kdo se o ní podělí.

Publikováno pod: .net technology , code snippet
2
X

Odhalujeme FlowLayoutPanel a TableLayoutPanel

Tentokrát se ve svém odhalování .NETu zaměřím na dva nové panely v .NET 2.0 a to konkrétně na FlowLayoutPanel a TableLayoutPanel. V obou případech se jedná o nevizuální prvky, které slouží jako container pro umístění dalších winform kontrolů na formulář.

TableLayoutPanel

Jestliže se zabýváte vedle tvorby winform aplikací také vývojem web aplikací určitě znáte tabulkový layout. A právě pro tvorbu tabulkového layoutu je určen TableLayoutPanel, jak ostatně již vyplývá z jeho názvu. Můžete tak do panelu přidávat řádky nebo sloupečky, a jednotlivé buňky seskupovat. Každá buňka pak slouží k vložení jednoho jediného kontrolu.

I mě se tento způsob umístění prvků na formulář líbil a našel jsem pro něj uplatnění ve své aplikaci, ale malinko mě překvapil. A než jsem stačil nalézt chybu, uběhla nějaká ta hodinka. Co se vlastně stalo? Jak už to tak bývá, nejdříve jsem si s daným panelem hrál a přidával a odebíral sloupčky a řádky. Poté co jsem si řekl, že znám možnosti designera, smazal jsem všechny řádky a začal prvky vkládat v runtime. Účelem mého snažení totiž bylo vkládání jednotlivých kontrolů na základě definované a načtené konfigurace při běhu aplikace. Jaké však bylo mé překvapení, když se zobrazilo nejdříve prázdné místo a vložené kontroly se nacházely až někde hluboko pod okrajem formuláře.

Ano, přestože jsem vymazal sloupčky i řádky pomocí grafického designeru. Tyto zůstaly zachovány v inicializaci formuláře/panelu. Než mě však napadlo se podívat na počet vytvořených řádků, uvažoval jsem o úplně jiných chybách ... chjo. A tak ponaučení pro příště, překontrolovat i formular.Designer.cs soubor, ne vždy se designeru povede vše odstranit.

FlowLayoutPanel

O tomto prvku již jenom krátce. Jelikož také slouží jako kontainer pro další kontroly a to tím způsobem, že umožňuje jejich pozicování za sebe a to jedním z několika možných způsobů jejich toku. Opět je zde analogie z web aplikací a tentokráte pro beztabulkový layout.

Následující, je ale spíše pro oba dnes zmíněné panely. Je známé, že pokud umístíme na formulář nebo usercontrol některé prvky (většinou se jedná o složitější prvky jako je StripControl) nelze je v poděděných formulářích nebo usercontrolech editovat a to ani po nastavení jejich visibility na public nebo protected.

Já jsem tuto funkcionalitu však potřeboval využít a tak jsem se pokusil poodhalit opět něco z .netu a výsledek se dostavil. Vytvořil jsem si nový kontrol, který byl poděděn z FlowLayoutPanelu a přidal mu atribut, konkrétně DesignerAtribut pro Panel.

[Designer("System.Windows.Forms.Design.PanelDesigner, System.Design")]

S touto úpravou jsem pak měl zpřístupněn panel i ve zděděných formulářích a mohl tak vesele designovat dataentry formuláře. A po přečtení tohoto příspěvku to dokážete i vy.

Zamyšlení k vylepšení

Ač nejsem velkým příznivcem naklikávání aplikací, občas se rychlý návrh formuláře pro editaci záznamu hodí a k tomuto účelu má Visual Studio 2005 poměrně pěkný designer. Co bych však uvítal je možnost zvolit si, že chci takto vygenerovaný formulář umístit právě do TableLayoutPanelu. Přeci jen mi přijde, že v něm jsou prvky lépe pozicovány a celý formulář pak vypadá úhledněji.

Publikováno pod: .net technology , code snippet
22
IX

Jednoduchý web sql editor

Vytvořil jsem si jednoduchý sql editor. Záměrně zmiňuji, že se jedná o jednoduchý webový sql editor, který umí pouze to základní, co jsem požadoval. A z jakého důvodu jsem se rozhodl o něm napsat? Myslím si totiž, že podobný editor může být pro někoho stejně užitečný jako je pro mě.

SqlExpress na webhostingu

Tím hlavním důvodem je to, že pokud stejně jako já máte hosting na kterém je provozován SQL EXPRESS 2005 a používáte jej pomocí AttachDBFilename není dostupný žádný nástroj, jak se k databázi připojit. A to mě dovedlo k tomu, že jsem napsal tento velice jednoduchý web sql editor.

V rozbalovacím seznamu je možné vybraz jednu z dostupných databází nakonfigurovaných pomocí connectionStrings. Do připraveného textového pole je pak možné vkládat jakékoli sql dotazy (SELECT, UPDATE atd.) Není problémem vložit i několik SELECT dotazů za sebe a ty spustit společně. Výsledek se pak zobrazí ve formě resultsetů uspořádaných do tabulek.

Jednotlivé příkazy jsou uchovány v historii a je tak možné se k nim jednoduše dostat a provést jejich spuštění znovu.

Architektura

Architektura této aplikace je velice jednoduchá. Jelikož jsem si chtěl vyzkoušet AJAX Pro, použil jsem k přenosu dat z/na server výhod AJAX technologie. Tím se mi také podařilo částečně zmenšit objem přenášených dat, neboť se přenáší skutečně jen data a nikoli i jejich reprezentace.

Jelikož jsem potřeboval zajistit výpis dat až na klientovi (tedy v prohlížeči) jako rozumným řešením mi přišlo zvolit XSL transformaci. Ta na základě definice XSD vytvoří tabulku a vypíše data. Díky tomuto řešení jsem se tak poměrně elegantně vypořádal se zpracováním NULL hodnot, a určitě by bylo možné i lépe formátovat tabulku na základě datových typů - tato funkcionalita však implementována zatím není. Malým mínusem, který mi však nevadí je provázanost na IE a instancování msxml2.domdocument, pokud někdo ví, jak toto vytvořit univerzálně má možnost nechat řešení v komentářích.

Vzhled aplikace prodává, o tom jsem již psal, a tak jsem se rozhodl osladit i tuto aplikaci pověstnou třešničku na dortu a použít nifty corners od Alessandro Fulciniti. (Díky) Nic Vám však nebrání v tom, změnit si vzhled dle vlastních potřeb.

Zabezpečení

Určitě by bylo velice nemilé, pokud by k takovéto aplikaci měl přístup každý návštěvník. Samozřejmě by bylo možné řídit přístup pomocí oprávnění v souboru web.config, avšak to je nedostatečné v případě použití aplikace jakou je např. Community server, na níž je provozován tento blog. Proto je přístup na stránky řízen pomocí konfigurovatelného security managera. V případě, že potřebujete řídit specificky přístup k editoru, postačí implementovat rozhraní IEditorAuthorize z assembly JiravaNet.Data.SqlEditor.Authorize a napsat vlastní implementaci. V sekci authorizeManager souboru web.config poté tuto implementaci uvést a nakonfigurovat. Přístup k editoru má v mém případě pouze CS administrátor a při přístupu z localhost není autorizace prováděna vůbec.

Rozšíření

Jestliže se Vám bude zdát, že by tento jednoduchý web sql editor mohl umět více, nebojte se svoje náměty zamechat v komentářích, pokud budu mít chvilku, pokusím se je implementovat a rozšířit editor o další důležité schopnosti. Zdrojové kódy, byť na nich není nic převratného, mohu poskytnout na vyžádání.

Zdroje

Web SQL editor ke stažení.

Update

Samozřejmě je možné s tímto editorem použít i jakoukoli jinou databázi, nejen SQL EXPRESS 2005, která bude správně konfigurována.

20
IX

Uchování ViewState mimo asp.net stránku

O tom, že protokol http je bezstavový je jeho vlastnost se kterou se musí vypořádat nejeden vývojář webových aplikací. Microsoft přišel v asp.net s tím, používat pro uchování stavu požadavků mezi jednotlivými requesty klienta, ViewState. ViewState je ve výchozím nastavení webového projektu povolen a jeho uchování se děje na základě vloženého input prvku typu hidden do renderované HTML stránky.

Tento způsob uchování ViewState není jediný možný a již ve verzi asp.net 1.x byla možnost jej za pomoci přepsání dvou metod změnit. ASP.NET 2.0 však jde ještě dál a poskytuje přímo abstraktní třídu PageStatePersister, ve které stačí přepsat dvě metody pro uložení a načtení ViewState a ControlState a stav uložit dle návrhu aplikace. V tomto článečku ukáži, jak takový stav uložit do databáze.

Pro napsání tohoto příspěvku, s poměrně triviálním kódem, jsem se rozhodl z toho důvodu, že se opět rozbouřily vody kolem asp.net a jeho renderování výstupu HTML na klienta. Nejsem si jist, zda to rozpoutal Borber s uveřejněním své bakalářské práce, na kterou reagoval Jakub Vrána. Nebo to bylo až poté, co se DGX pozastavil nad výroky Marcuse, a kdy jsem se do debaty vložil také osobně?

Hnedka na úvod musím říci, že ViewState využívám, snažím se však o to, aby byl využívám účelně a jeho velikost zbytečně nebobtnala. Proto je vždy důležité zvolit správné UI kontroly a v případech kdy to jde, zakázat ViewState zcela. Jelikož píši z převážné většiny intranetové aplikace, nebráním se ViewState využívat. Avšak přišlo mi velice neefektivní jej přenášet při každém požadavku na klienta a zase zpět. Také proto jsem zvolil uchování stavu na serveru a to přímo v databázi - přeci jen v aplikacích je těch dotazů do db několik a jeden dotaz navíc je téměř zanedbatelný.

Vlastní implementace

Důležité je říci stránce, aby používala náš vlastní persister. V případě, že používáte vlastní poděděnou třídu Page jako výchozí pro všechny ostatní, což z vlastní zkušenosti doporučuji, je postačující přepsat property PageStatePersister

protected override PageStatePersister PageStatePersister {
 get {
  return new DbPagePersister(Page, "connectionStringKey");;
 }
}

Jestliže nemáte stránky navrženy výše uvedeným způsobem, nemusíte ještě zoufat. Můžete využít PageAdapter, a obdobně zde přepsat metodu GetStatePersister(), následně pomocí souboru .browser tento adaptér pro generování stránek přiřadit.

Dříve však než můžeme zaregistrovat vlastní persister, musíme si jej vytvořit. Vytvoříme tedy novou třídu a podědíme ji od abstraktní třídy PageStatePersister. Zde přepíšeme dvě metody pro uložení Save() a načtení Load() stavu. Předpokládám, že každý umí uložit data do databáze a tak tento krok přeskočím, nicméně je v přiložené ukázce implementován. Co je však důležité, jakým způsobem bude identifikována stránka, abychom mohli načíst její stav zpět. To je zajištěno pomocí registrace hidden pole a přiřazení unikátního řetězce Guid. Tento je jako jediný odeslán na výstup stránky a při zobrazení zdrojového kódu jej zde naleznete.

Pod čarou

Pokud se podíváte na výsledný zdrojový kód, možná vás překvapí, že se zde vyskytuje hidden pole nazvané __VIEWSTATE avšak je prázdné. Toto pole se mi však nepodařilo využít pro uložení jednoznačného identifikátoru, stejně tak se mi nepodařilo pole odstranit z finálního výstupu. Tím ovšem neříkám, že to ve výsledku nelze, ale o tom až příště.

Zdroje

Ukázka ke stažení.

Publikováno pod: .net technology , code snippet
7
IX

Odhalujeme .net - SqlParameter

Jistě tu situaci zná každý vývojář. Říkáte si, že tohle znám, to se chová tímto definovaným způsobem a nemůže mě nic zaskočit. Jaké je pak následné překvapení a jak se odhalují takto nepředvídané situace o to bych se rád podělil v následujících odstavcích a nejen v nich. Přeci jen těch nástrah a postřehů mám za dobu co vyvíjím v .netu vícero a tak nezůstane jen u tohoto příspěvku.

Zrovna první nástraha je z poměrně blízké doby a jednalo se o SqlParameter, se kterým jsem "zápasil". Ve všech svých dotazech používám parametry, přeci jen nejsem hazardér ani začátečník, abych si dovolil tento způsob zápisu nepoužívat.

Při volání uložených procedur je pak možné, čehož rád využívám, mít parametr jako výstupní, případně kombinovaný - vstupně/výstupní. V takovém případě je však nutné výstupní hodnotu z property Value přetypovat na správný datový typ pro pozdější použití. Nejčastěji tedy použijeme tento zápis:

int result = (int)outputParameter.Value;

Jenže najednou nastala situace, se kterou jsem nepočítal. Na vývojovém prostředí vše fungovalo správně a nejevilo sebemenší chybičku. Ovšem v ostrém prostředí byla reportována chyba: Specified cast is not valid a odkaz na řádek s přebíráním výstupní hodnoty z volané uložené procedury. Zpočátku jsem byl velice nedůvěřivý a tak jsem prověřoval, zda je struktura databáze shodná a je použita stejná definice procedury. Vše ovšem souhlasilo. Jak si jistě dokážete sami představit, v tu chvíli jsem začal být lehce nervozní a v rozpacích, navíc nebylo možné se na vzdálený počítač připojit a tak jsem byl odkázán pouze na obsluhu. Ta mi také potvrdila, že jsou nainstalovány všechny verze .net frameworku - adresář %SysDir%\Microsoft.Net\Framework obsahoval všechny tři adresáře s verzemi fw.

Ač je to velice nepravděpodobné, říkal jsem si, že by problém mohl být ten, že aplikace, byť kompilovaná na verzi 1.1 tuto verzi frameworku nepoužívá. Pro vnitřní klid jsem proto vložil do konfiguračního souboru tento element:



jenž zajistí/vynutí použití právě dané verze .net frameworku. A světe div se, verze 1.1 frameworku nebyla nainstalována. Určitě mi uvěříte mé uklidnění.

Návratová hodnota z SqlParameter

Jak předcházející odstavce souvisí se zmíněnou třídou SqlParameter? Ve verzi .net frameworku 2.0 se změnil datový typ, který je navrácen při volání dotazu z jednoduchého hodnotového typu na ekvivalentní Sql strukturu. Pro získání návratové hodnoty tak použijeme zápis:

SqlInt32 result = (SqlInt32)outpuParameter.Value;

Důvod vyvolání výjimky System.InvalidCastException byl tedy ozřejmen a po doinstalování požadované verze vše začalo sprvávně pracovat.

Dalším odhalením pak byla skutečnost, že .net framework 2.0 v průběhu své instalace vytvoří zároveň i adresáře pojmenované po předchozích verzích frameworku. Tím je však zabráněno možnosti snadno identifikovat všechny nainstalované verze frameworku. A tím také došlo nejen k mému zmatení a nutnosti odhalovat další zákoutí vývoje pro .net.

Otázka: Znáte lepší způsob pro zjištění všech instalovaných verzí .netu?

Pod čarou

Nejsem si jistý správností tohoto tvrzení, ale je pravdou, že .net 2.0 využívá některých knihoven z předchozích verzí a tyto zároveň s instalací kopíruje do správných adresářů.(?)

Publikováno pod: .net technology
2
IV

Practical .NET2 and C#2

Malá otázka pro všechny nadšence v .net. V minulých dnech vyšla kniha Practical .NET2 and C#2. Nejen podle referencí, ale i podle toho, jak jsem přímo "zhltnul" volně dostupné kapitoly, se chci optat, zda si bude někdo tuto knihu objednávat. Případně se nechce připojit k mojí objednávce. Přijde mi, že se jedná o jednu z knih typu MUST HAVE, která po delší době vyšla a nesmí chybět v programátorské knihovničce.

V případě že máte zájem, nechte zprávičku a určitě se domluvíme.

UPDATE: objednáno.

Publikováno pod: .net technology