Klávesové zkratky na tomto webu - rozšířené Na obsah stránky

Persistence modelu pomocí ActiveRecord

15.16 - 21. ledna 2009 | ASP.NET 2.0

V architektuře naší MVC aplikace jsme se dostali již poměrně daleko. Vybrali jsme si šablonovací systém, máme vyřešenou integraci s IoC kontejnerem, vymazlené routování, připravené model bindery a teď je na čase nějakým způsobem model persistovat. Existuje mnoho způsobů, jak toho dosáhnout.

  1. Persistenci si můžete řešit sami na úrovni ADO.NET. Jenže proč řešit něco, co už někdo stokrát vyřešil?
  2. Použít nějaký ORM nástroj.

ORM nástrojů na výběr máme dnes tolik, že je stěží na prstech spočítáme, jaký si tedy vybrat? Pro mnohé bude první volbou LINQ to SQL. Pro jednoduché mapování (1:1) a tam, kde je možné být závislý pouze na MS SQL, je toto řešení dostačující. Osobně preferuju malinko složitější cestu, ale ve výsledku myslím, že mnohem mocnější. :)

Castle ActiveRecord a Repository pattern

Já ve svých posledních proktech používám Castle ActiveRecord, což je implemenatce návrhového vzoru ActiveRecord nad ORM frameworkem NHibernate. V mnoha ohledech práci s NHibernatem značně zjednodušuje, ať už je to mapování, automatickou správu session a podobně. Způsoby užití jsme už popsal ve spotu ActiveRecord vs. Repository pattern. Další výhodou je, že vše, co funguje v NHibernate (LINQ, Spatial, vlastní mapovací typy), můžete použí i s Castle ActiveRecord.

Datové třídy však nedědím z bázové třídy ActiveRecordBase, ale používám Repository, která se stará o CRUD operace s entitou. Pokud chcete mít mapování a závislost na ActiveRecord snadno odstranitelnou, můžete mapovací atributy vyčlenit třeba do samostatného partial souboru. Ale nejspíš nikdy v životním cyklu vaší aplikace nebudete ORM framework měnit, takže se trápit metadaty o databázovém schema je celkem zbytečné…

Základem pro repository je generické rozhraní IRepository<>, pro snadnou automatickou registraci repositoří v kontejneru ještě nadefinujeme ještě i negenerické rozhraní:

using Castle.ActiveRecord;

public interface IRepository {}

public interface IRepository<Tentity> : IRepository where TEntity : class {
  TEntity FindById(int id);
  void Save(TEntity entity);
  void Delete(TEntity entity);
}

public abstract class ActiveRecordRepositoryBase<TEntity>
  : IRepository<TEntity> where TEntity : class {
  public virtual TEntity FindById(int id) {
    return ActiveRecordMediator<TEntity>.FindByPrimaryKey(id);
  }
  public virtual void Save(TEntity entity) {
    ActiveRecordMediator<TEntity>.SaveAndFlush(entity);
  }
  public virtual void Delete(TEntity entity) {
    ActiveRecordMediator<TEntity>.DeleteAndFlush(entity);
  }
}

Pojďme si podporu pro ActiveRecord integrovat do naší MVC aplikace.

Integrace přes Binsor

Výhodou projektů z Castle, je, že se mezi sebou dokážou integrovat a využívat navzájem výhod své synergie. Nejprve si do projektu přidáme referenci na knihovnu Castle.ActiveRecord a ještě Castle.Facilities.ActiveRecordIntegration. Následně zaregistrujeme v souboru Windsor.boo facility pro integraci ActiveRecordu do IoC kontejneru:

import System.Reflection

// podpora ActiveRecord v kontejneru
facility ActiveRecordFacility:
  configuration:
    @isWeb = true, isDebug = false
    assemblies = [ Assembly.Load("MyApplication.Entities") ]
    config(keyvalues, item: add):
      show_sql = true
      command_timeout = 500
      dialect = 'NHibernate.Dialect.MsSql2005Dialect'
      connection.provider = 'NHibernate.Connection.DriverConnectionProvider'
      connection.driver_class = 'NHibernate.Driver.SqlClientDriver'
      connection.connection_string_name = 'CONN_DEMO'

Teď ještě potřebujeme ve web.configu přidat ConnectionString pod klíčem CONN_DEMO a volitelně přidat životnost session na jeden request. To uděláte tak, že do sekce system.web\httpModules přidáte následující modul:

<add
  name="PerRequestSessionScope"
  type="Castle.ActiveRecord.Framework.SessionScopeWebModule, Castle.ActiveRecord"/>

To má za výhodu to, že všechny vaše dotazy za jeden request se chovají jako jedna transakce. Takže integrace frameworku, je hotová. Teď ještě přidáme automatickou registraci samotných repositoří.

for repository in AllTypesBased of IRepository("MyApplication.Entities"):
  component repository.Name.ToLower(), repository.GetInterfaces()[0], repository:
    lifestyle PerWebRequest

Tímto se zaregistrují všechny repository, které dědí z ActiveRecordRepositoryBase a jsou pak ve vašich komponentách dostupné jako IRepository<User> (příklad pro entitu User). Pokud budete mít v repository více metod, je dobré vytvořit pro ně kontrakt, který obsahuje kontrakt generické repository. Například takto:

public interface IUsersRepository : IRepository<User> {
  User FindUserByEmail(string email);
}

Registrace takovýchto komponent už je o něco složitější, ale dá se to také zvládnout. Nejprve si zavedeme konvenci, že repository, které takovéto kontrakty implementují, se budou jmenovat až na I na začátku stejně. :) Takže pro kontrakt IUsersRepository budeme mít konkrétní implementaci UsersRepository atd. Pro jejich registraci využijeme metodu System.Type.FindInterfaces, která bere jako první argument delegát na vyhledávací funkci a druhý argument jsou hledací kritéria. Takže si vytvoříme funkci, která splňuje kontrakt delegáta, a následně ji hned využijeme pro registraci:

def contains_name(t as Type, o as Object):
  return t.Name.Contains(o.ToString())

for repository in AllTypesBased of IRepository("MyApplication.Entities"):
  repository_interface = repository.FindInterfaces(contains_name, repository.Name)
  component repository.Name.ToLower(), repository_interface, repository:
    lifestyle PerWebRequest

Cool ne? Pár řádků konfigurace a nejspíš máme vystaráno, tedy když dodržíme stanovenou konvenci, tak už se o registraci komponent datové vrstvy nemusíme starat. Stejně tak už máme zaregistrované model bindery a controllery. Trošku nám to konfigurace povyrostla, ale díky možnostem, které nám přináší Binsor, je to jen zlomek toho, co by bylo potřeba napsat v XML.

Projektík se nám pomalu rozrůstá, sice stále nic nedělá, ale je to dobrý základ pro pořádný web. Pokusím se ho hodit někam do SVN, aby bylo lehčí se v projektu orientovat a byly vidět jednotlivé změny.

K WebExpu ještě jednou a pořádně

16.19 - 25. října 2008 | Webdesign

Už je to týden, co nám skončila přednáška o ASP.NET 3.5 / futures na konferenci WebExpo 2008. Rád bych se k této konferenci ještě ohlédl.

Moje prezentace

Když mě začátkem léta oslovil Vašek Stoupa, jestli nechci přednášet o ASP.NET MVC na WebExpu, měl jsem zprvu strach. Nikdy jsem veřejně nepřednášel a z malých slideshow, které jsem dělal pro kolegy nebo ve škole, jsem si byl jistý, že mé prezentační schopnosti nejsou skoro žádné. Ale pak jsem si řekl, že zkusit bych to mohl, přinejmenším je to dobrá zkušenost a raději jsem požádal Borka, aby se ke mně přidal. Proč? Protože už jsem ho viděl přednášet na WebCampu a bylo to dobré.

Takže jsme se domluvili, že přednáška bude mít trochu širší záběr než jen ASP.NET MVC, které v té době bylo pouze v ukázkových verzích. V průběhu září jsme vymysleli nějakou osnovu, Borek založil SVN repository a začali jsme připravovat prezentaci.

Nejprve jsem udělal ukázku na využití ADO.NET Data Services ve spolupráci s ASP.NET AJAX (tu najdete přibalenou). Krom toho, že ukazuje základy konzumace RESTových Data Services, tak je i hezkou ukázkou toho, jak takové služby stavět nejen nad Entity Frameworkem, ale i nad ActiveRecord/NHi­bernate. No, ukázka není úplně dokončená, protože jsem se jí přestal věnovat a už jsem nenašel chuť jí dokončit, ale základní koncepce je snad pochopitelná – snažil jsem se vše okomentovat.

Osobně nemám rád psaní zbytečného kódu. Nejsem zastáncem zbytečných ukázkových aplikací, testovacích utilitek a tak. Takže už jsem žádné další ukázkové aplikace nepsal a rozhodl se další možnosti ASP.NET ukázat na již hotových aplikacích, se kterými mám něco společného.

Základní koncept komponent a Master pages jsem se tedy rozhodl ukázat – ať nechodíme daleko – na šabloně tohoto blogu. O něco pokročilejší komponentový framework jsem pak ukazoval na šabloně obchody.atlas.cz. Tahle jedna šablona je v podstatě celý web. Bez knihovny je sice mrtvá a ještě chyběj pravidla URL rewritingu, ale jinak je tam vše. Tyhle dvě ukázky najdete taktéž přibalené.

Poslední mou ukázkou byla aplikace, kterou jsem psal kvůli potřebě naučit se ASP.NET MVC a ADO.NET Data Services prakticky ještě před konferencí a zároveň abychom se v práci zbavili nutnosti zapisovat si příchody někam na papír (formulář) a pak na konci měsíce počítat, kolik kdo dostane stravenek :). Tak vznikla docházka a taky rozcestník projektů a tím pádem základ Twareg.Intranet. Shodou okolností to možná bude i naše první komerčně prodávaná aplikace. Hezký osud bokovky…

Takže na tomto webu jsem se pokusil ukázat, jak se dělá routing, jak je ten systém modulární. Jak deklarativně pomocí atributů nastavit autorizaci k akcím a jak akce snadno přejmenovat. Na víc už moc nezbýval čas. Tahle ukázka přibalená není. Namísto ní najdete Borkovy REST služby postavené nad ASP.NET MVC, které jsme bohužel nestihli ukázat.

Co se týče mého vystoupení, tak moc spokojený nejsem, vůbec se to nedostalo ani na spodní hranici mých představ o dobré přednášce – naštěstí tam byl Borek, aby to zachránil.

Author Stream ty slajdy trochu rozsypal, ale lepší než nic. Jinak pokud si chcete slajdy nebo ukázky stáhnout, pokračujte na Slajdy a ukázky z WebExpa. Pokud vás toto téma zajímá určitě najdete spoustu zajímavých futures bits na Codeplexu. Některá témata z přednášky bych rád rozebral podrobněji tady na blogu, ale až někdy jindy.

Shlédnuté prezentace

Na WebExpu jsem naštěstí nebyl jen jako pokus o přednášejícího, ale i jako divák. Oproti původnímu plánu jsem nakonec navštívil trochu jiné přednášky. Jako opravdu výbornou můžu označit přednášku Juraje Michálka o Flexu. Hodně dobrá byla nejspíš i Karmiho přednáška o Ruby on Rails, ale zastihl jsem jen asi posledních 25 min. Přednáška o Nette z úst nejzasvěcenějšího byla zábavná, nicméně s plánovaným školením PHP frameworky na paměti značně zredukovaná.

Mezi pro mě obsahově hodnotné a pořád dobře odprezentované bych ještě rád zařadil Dagiho přednášku o Springu, přednášku Vlastimila Pečínky o architektuře v Seznamu a přednášku o SproutCore od Antonína Hildebranda. Sice jsem nedostal odpověď na otázku, jestli to funguje i bez JavaScriptu, ale i tak přednášku hodnotím jako přínosnou a můžu rubistům tiše závidět ;).

Sociální vlivy

Na tuhle akci jsem nejvíc těšil hlavně kvůli lidem. Já moc na tydlety akce nechodím, ale jednou za čas se potkat s lidmi, které často čtu, není špatné. Rád jsem osobně potkal i některé nové tváře, které jsem dosud nečetl a třeba to napravím…

Na závěr

Na závěr patří především velíké díky Vaškovi, za velikou zkušenost, za zorganizování téhle veliké party se spostou zajímavých osobností a se širokým záběrem témat. Je dobré když se člověk může podívat na to jak to dělaj jinde a něčemu se třaba přiučit nebo prodiskutovat své pohledy na věc. Ono táhnout konferenci až do první hodiny ranní není žádná sranda. Respekt!

Jo a málem bych zapomněl, na LinkedIn jsem vytvořil k této konferenci skupinu, takže pokud jste se ještě do ní nepřidali, neváhejte a udělejte to ještě teď. A pokud vás zajímají slajdy ostatních nebo chcte nasdílet své, využijte eventu na slide share.

Binsor – síla konfigurace

15.18 - 25. srpna 2008 | ASP.NET 2.0

Pokud se dostanete do stádia, kdy potřebujete takovou architekturu, kde je potřeba používat plug-iny třetí strany, kde je potřeba snadno vyměnit komponentu za jinou, přichází ke slovu nějaký druh konfigurace.

Velice často se můžeme setkat s konfigurací komponent v XML. Ať už je to Provider pattern známý z ASP.NET, či vlastní konfigurační sekce, nebo konfigurace Windsor kontejneru, pořád tu máme XML. Jeho ohromnou výhodou je, že se dají systémové komponenty snadno překonfigurovat bez nutnosti celý systém překompilovat. Stačí pouhý restart aplikace. Navíc nástrojů na editaci a validaci XML máme nepočítaně, takže změnu konfigurace zvládne téměř každý.

Velkou nevýhodou XML, je jeho omezené výrazivo. Špatně se v něm píše foreach nebo if. Prostě na složitější konstrukce je potřeba programovací jazyk. A nebo skriptovací!

Boo na scénu

Boo je staticky typovaný objektový jazyk nad CLI (dot net) inspirovaný syntaxí Pythonu. Jeho hlavní silou je metaprogramování. Na úrovni kompilátoru se snadno dají psát makra. Takových maker lze využít k tvorbě přehledných DSL a jednou z takových je i Binsor.

Windsor + Boo = Binsor

Windsor je IoC kontejner na platformě dot net a je součástí opensource projektu Castle. Windsor má v základu dvě možnosti jak konfigurovat komponenty.

  1. Programově na úrovni mikrokernelu.
  2. XML konfigurací.

XML konfigurace je nejčastěji užívanou možností, kvůli výše popsaným výhodám. V trunku se nedávnou objevila i konfigurace pomocí DSL na principu fluent interface přímo v C#. Taková konfigurace je velice pěkná, ale je tu pořád nutnost při každé změně znova celý projekt kompilovat. Proto je tu Binsor, který si bere sílu programovacího jazyka, efektnost XML konfigurace a navíc jednoduchost a přímočarost syntaxe.

Konfigurace komponent

Nejčastější aktivitou s Binsorem nejspíš bude registrace komponent. :)

component 'my_component', IServiceContract, ServiceImplementation:
    # nastavime parametr konstruktoru
    constructorParameter = 10
    # nastavime vlastnost sluzby
    SomeProperty = "Hello Word!"

Kód je v celku jednoduchý. Na prvním řádku začínamé klíčovým slovem component, které říká, že registrujeme komponentu. Prvním parametrem je název komponenty, přes který se na ní můžeme odkazovat. Druhý parametr je rozhranní služby a třetí je konkrétní implementace, která bude při rozpoznání kontejnerem vrácena, např. IoC.Container.Resolve<IServiceContract>(). Za dvojtečkou pokračuje výčet nastavovaných vlastností a parametrů. Můžeme takto nastavovat i speciální vlastnost ovlivňující životnost objektu.

component HttpRequest:
    lifestyle Singleton

Všimněte si, že se ani nemusí při registraci uvádět referenční název nebo abstraktní typ. Může se klidně rovnou registrovat typ konkrétní, který se bude v tomto případě chovat jako singleton. Takovéto ukázky jsou fešné, ale nic, co bychom nezvládli pomocí XML. Pojďme trochu dál.

for type in AllTypesBased of Controller("MyApplication.Web"):
    component type

Tento kód zaregistruje všechny controllery (třídy, které jsou potomky třídy Controller) z assembly MyApplication.Web. Krom generické metody AllTypesBased, je tu ještě generická metoda AllTypesWithAttribute a negenerická AllTypes. Všechny mají jako parametr název assembly, jejíž typy procházejí.

Facility

Neméně důležitou součástí konfigurace jsou facility, které dodávají kontejneru nové možnosti a zapouzdřují větší sady komponent do logických jednotek. Pro ukázku konfigurace ActiveRecord komponent pomocí Binsoru:

facility ActiveRecordFacility:
    configuration:
        @isWeb = true, isDebug = true
        assemblies = [ Assembly.Load("MyApplication.Entities") ]
        config(keyvalues, item: add):
            show_sql = true
            command_timeout = 5000
            cache.foo.use_query_cache = false
            dialect = 'NHibernate.Dialect.MsSql2005Dialect'
            connection.provider = 'NHibernate.Connection.DriverConnectionProvider'
            connection.driver_class = 'NHibernate.Driver.SqlClientDriver'
            connection.connection_string = 'connectionString1'

Shrnutí

Osobně se mi možnosti konfigurace přes Binsor velice líbí, ale je celkem možné, že ne každému to může vyhovovat. Pokud ale používáte Windsor a přijde vám XML konfigurace nepřehledná, je toto možná cesta, jak z toho ven. Pokud chcete nějaké lepší příklady, doporučuju si stáhnout SVN repository https://rhino-tools.svn.sourceforge.net/svnroot/rhino-tools/trunk/rhino-commons a projít si testy. Jako editor se mi osvědčil SharpDevelop, který má podporu pro Boo přímo v základu, nebo doinstalovat BooLang Studio do Visual Studia.

Tagy: , ,

Active Record vs. Repository pattern

12.38 - 21. května 2008 | ASP.NET 2.0

Dnes se podíváme na dva návrhové vzory z oblasti přístupu k datům, které používají zcela odlišnou filosofii, ale nakonec si ukážeme, že jejich kombinací, můžeme získat celkem zajímavé výsledky.

Active Record

Návrhový vzor Active Record staví na předpokladu, že základem aplikace je databázový model a od něj se vše odvíjí. Každý řádek tabulky je reprezentován konkrétní instancí objektu. Většinou je takový objekt odvozen od bázové třídy, která implementuje potřebné rozhranní pro persistenci objektu – typicky CRUD metody.

Diagram vzoru ActiveRecord

Tento vzor se hojně využívá v různých ORM frameworcích. Je součástí dnes velmi módních frameworků Ruby on Rails, django nebo Castle, které na něm stavějí svůj datový model a díky velice snadnému mapování dokážete napsat (vygenerovat) kostru databázové aplikace během několika málo minut.

Pro velice jednoduché aplikace může být tento vzor, díky své jednoduchosti, vhodný. Jenže porušuje několik pravidel dobrého objektového návrhu (persistence ignorance, single responsibility, pevně daná bázová třída, atd.).

Repository

Návrhový vzor Repository je základním kamenem doménou řízeného návrhu. Model aplikace nemá ponětí o tom, jakým způsobem je persistován. O to se stará právě Repository. Navíc díky tomu, že se o persistenci stará cizí objekt, stačí nám znát pouze jeho rozhranní a v případě potřeby ho snadno nahradit jiným.

Diagram vzoru Repository

Kombinace

Teď zabrousím do konkrétnějších implementací a to do ActiveRecord z projektu Castle. Tako konkrétní implementace je postavená na běhovém prostření dotnet a jako svůj základ používá ORM nástroj NHibernate.

Nejpřímější cesta jak s ním pracovat, je podědit třídu z bázové třídy ActiveRecordBase a označit ji a její vlastnosti patřičnými atributy:

[ActiveRecord]
public class User : ActiveRecordBase<User> {
  [PrimaryKey] public int Id { get; set; }
  [Property] public string Name { get; set; }
  [Property] public string Email { get; set; }
  [Property] public string Login { get; set; }
  [Property] public string Password { get; set; }
}

A můžeme pracovat. Autoři si však byli vědomi toho, že vzor Active Record nemusí vyhovovat všem a přidali statickou třídu ActiveRecordMediator, který dokáže posloužit jako základ pro Repository. Třída pak nemusí dědit z ActiveRecordBase:

[ActiveRecord]
public class User {
  [PrimaryKey] public int Id { get; set; }
  [Property] public string Name { get; set; }
  [Property] public string Email { get; set; }
  [Property] public string Login { get; set; }
  [Property] public string Password { get; set; }
}

public class UsersRepository : IRepository<User> {
  public User Load(int id) {
    return ActiveRecordMediator<User>.FindByPrimaryKey(id);
  }
  public void Save(User obj) {
    ActiveRecordMediator<User>.Save(obj);
  }
  public void Delete(User  obj) {
    ActiveRecordMediator<User>.Delete(obj);
  }
}

To už je o něco lepší, ale stále máme v aplikačním modelu silnou vazbu na datový model. Můžeme se posunout o level dál a zkombinovat oba vzory tak, abychom z nich vytěžili co nejvíce. Základní myšlenkou je to, že v aplikaci budeme mít jak datový model, tak doménový. Datový model se bude pomocí Active Record starat o persistenci a Repository poslouží k transformaci doménového modelu na ten datový.

Něco podobného můžete najít v seriálu, který píše Rob Conery, kde používá zjednodušenou Repository, IQueryable jako filtry a LINQ2SQL jako datový model. Velice zajímavé, doporučuji ke shlédnutí.

Tagy: , ,

Redakční systém na ASP.NET MVC

18.56 - 23. prosince 2007 | Webdesign

Rozhodl jsem se, že, jako praktickou ukázku použití TDD a ASP.NET MVC (dále jen MVC), budu psát seriálek, výsledkem něhož bude základ třetí verze redakčního systému Gryphoon.

Upozornění: Je možné, že některým věcem nebudete v průběhu čtení rozumět. Dopuručuji si přečíst související články, na jejichž základě tento seriál staví.

Už z této podstaty vyplívá, že půjde o OSS. Projekt je hostován na Codeplexu pod MS-PL. Dalším důležitým znakem je použití Texy.net jako základního kamene systému, spojení s databází bude zajišťovat Castle ActiveRecord, pro testování použiji xUnit.net a Rhino Mocks. Tím jsou nastíněny základní prvky architektury a můžeme se pomalu dát do práce.

Struktura projektu

Prozatím to vypadá na tři projekty v řešení:

  1. Rarous.Gryphoon – Knihovna, jádro systému, které bude obsahovat objekty doménového modelu, konfiguraci a další potřebné komponenty.
  2. Rarous.Grypho­on.Spec – Knihovna s jednotkovými testy. xUnit.net místo termínu test používá fakt, proto bude brát tento projekt jako specifikaci zbylých částí.
  3. Rarous.Grypho­on.Web – Webová aplikace. Projekt bude obsahovat webovou část tj. Controllery a View (řadiče a pohledy) a Helpery (pomocníky).

První řádky specifikace

Naší jedinou specifikací bude projekt Rarous.Grypho­on.Spec. Tím co je v něm dáno, by se měly řídit oba zbylé projekty. Dobrým zvykem v TDD je navrhovat systém od shora dolů. První věc, se kterou přijdete do styku, je URL. Zatím nebudu výchozí schéma URL měnit, proto ani nebudu psát testy na Routování (zatím). Defaultní schéma URL by mělo být už milionkrát otestované v rámci MVC projektu.

Takže budeme pokračovat dál a to k řadiči článku (ArticleController). Ten by měl být zodpovědný za vytváření článků nových, jejich následnou editaci, zobrazování a v poslední řadě i mazání.

V prvním CTP, zatím nejsou předdefinované Mock Objekty pro controllery, proto použijeme Test subclass pattern, pro ověření činnosti controlleru. Controller bude mít následující rozhranní:

Diagram IArticleController

A třída pro testování vypadá následovně:

public class TestArticleController : ArticleController {
  public string ActualViewName { get; set; }
  public string RedirectViewName { get; set; }
  public string ActualMasterName { get; set; }
  public object ActualViewData { get; set; }

  protected override void RenderView(string viewName, string masterName,
                                     object viewData) {
    ActualViewName = viewName;
    ActualMasterName = masterName;
    ActualViewData = viewData;
  }

  protected override void RedirectToAction(object values) {
    RedirectViewName = values.ToDictionary()["Action"];
  }
}

Teď můžeme napsat první test, který ověří, že pokud přijdeme na adresu /article/ otevře se nám editor nového článku. Pozn. Využívám výchozího schématu routeru [controller]/[action]/[id] -Pokud není action definovaná vybere se Index. V budoucnu ho změním na lepší, ale pro začátek stačí.

[Fact]
public void ArticleController_DefaultActionShouldShowEditor() {
  TestArticleController controller = new TestArticleController();

  controller.Index();

  Assert.Equal("Editor", controller.ActualViewName);
}

Spustíme test – neprojde. Aby test prošel, musíme doimplementovat metodu ArticleController.Index.

[ControllerAction]
public void Index() {
  RenderView("Editor");
}

Teď už by měl test projít. Jenže aby to fungovalo i na webu, musíme ještě dopsat View /Views/Article/Editor.aspx… Do příště za domácí úkol.

Závěrem

Aktuální stav je na codeplexu ke stažení, ale zdaleka není funkční. :) Průběžně ho budu s dalšími díly doplňovat. Příště tedy uděláme ukládání nových příspěvků a editaci. Když se pozorně podíváte na zdrojáky, zjistíte, že tak trochu cheatuju :)

Jo abych nezapoměl, pokud jste sem přišli přes RSS a ještě jste si nezměnili adresu feedu, učiňte tak zavčasu. Děkuji

Související

Tagy: ,

Problem ActiveRecord se SQL CE

20.17 - 27. listopadu 2007 | ASP.NET 2.0

Píšu takovou malou aplikaci, která používá SQL Compact Edition pro ukládání dat a Castle ActiveRecord jako persistenční vrstvu. Očekával jsem, bezproblémové použití, ale chyba lávky. To bych přišel o námět na tenhle spot.

Napoprvé jsem chtěl využít služeb LINQ to SQL, ale ten si s SQL CE moc nerozumí (tj. vůbec). Tak jsem tedy sáhl po ActiveRecord o kterém jsem četl, že se SQL CE umí (díky NHibernatu). Přidal jsem DB do projektu, nastavil konfiguraci následujícně:

<activerecord>
  <config>
    <add key="hibernate.dialect"
         value="NHibernate.Dialect.MsSqlCeDialect" />
    <add key="hibernate.connection.driver_class"
         value="NHibernate.Driver.SqlServerCeDriver" />
    <add key="hibernate.connection.provider"
         value="NHibernate.Connection.DriverConnectionProvider" />
    <add key="hibernate.connection.connection_string"
         value="Data Source=DbFile.sdf;" />
  </config>
</activerecord>

Spustím testy. Nic, spadlo to na výjimce, že NHibernate nemůže vytvořit Driver pro SQL CE. Po chvilce hledání jsem našel, že se musí u reference na Syste.Data.SqlServerCe nastavit vlastnost Copy Local na True a to i u testovacího projektu!

Tak jsem zas o něco chytřejší :)

Castle RC3 a Microsoft MVC

07.48 - 9. října 2007 | Webdesign

Vůbec jsem si toho nevšiml, ale RC3 verze Castle je již několik týdnů venku. Stáhnout si jí můžete ze SourceForge.

Další zajímavou zprávou je. že Microsoft pracuje na vlastním ASP.NET MVC frameworku, který bude umožňovat plnou testovatelnost, IoC kontejnery, ASPX jako view bez ViewState a Page lifecyklu a spoustu zajímavých vychytávek využívajících generika a nové možnosti C#3. První CTP by se měla objevit do konce roku a releas někdy na jaře roku příštího. Release by měl být podobný jako AJAX Extensions, časem se pak zařadí přímo do .net frameworku.

Zajímavý je pohled vývojářů MonoRailu. Vítají zdravou konkurenci a podle všeho se budou snažit využít všech výhod ASP.NET MVC a MonoRail budovat dále nad ním.

Související

Začínáme s jednokolejkou

16.10 - 14. srpna 2007 | ASP.NET 2.0

Jedním z fenoménů poslední doby ve webovém vývoji jsou bezesporu Ruby on Rails (RoR). Framework určený k RAD Agile vývoji používající objektový přístup a postavený na návrhových vzorech jako je MVC nebo Active Record. Framework je určený pro jazyk či platformu Ruby, to je jeho výhoda i omezení zároveň. Málokdo se má chuť nebo čas se po nocích učit novým jazykům a stávat se vícenásobným robotem.

RoR není rozhodně jediným projektem s podobnou filosofií. My dotneťáci máme krom WebForms, které se snaží přihnout webový vývoj desktopovým zvyklostem (událostmi řízený, stavový), podobný framework, který je navíc opensource. Tento framework se jmenuje MonoRail a oněm bude následující článek a možná i mini seriálek :)

MonoRail

Z názvu by se mohlo zdát, že má projekt něco společného s Monem, opensource implementací dotnetu, ale není tomu tak, krom toho, že MonoRail běží i na Monu 1.1. MonoRail je součást opensource projeku Castle, který si klade za cíl RAD v Enterprise prostředí. Jeho součástí jsou frameworky ActiveRecord (ORM Persistence layer postavený nad NHibernate), Windsor container (Inversion of Control), DynamicProxy (vytváří Proxy třídy z Interfejsů) a právě MonoRail. Všechny frameworky umějí pracovat samostatně, ale jejich největší síla je v jejich spolupráci.

Co je tedy MonoRail? Je to MVC framework inspirovaný ActionPackem běžící na platformně dotnet. Je to náhrada ASP.NET WebForms, ale ty mohou sloužit jako ViewEngine, nebo běžet v jedné aplikaci s MonoRails vedle sebe. Dalšími ViewEnginy jsou NVelocity (port Velocity pod dotnet) nebo Brail (Views jsou psaná v jazyce Boo, což je skriptovací Python like jazyk pro dotnet). Preferovanější je asi NVelocity, ale vývoj Brailu je živější, a WebForms se pro změnu skoro nepoužívají (kvůli PageLife cyklu, který v MonoRailu neexistuje). MonoRail se vám může oproti ASP.NET zdát oldskůlovější, ale opak je pravdou. MonoRail přináší zjednodušení, vrací se k webovému vývoji (bezestavový, Request/Response), staví na osvědčených metodách a zrychluje celý vývoj. Konec řečí, pojďme na věc :)

Model

Model obecně slouží jako zdroj/zpracovávač dat aplikace. Podle toho, jak je vaše aplikace složitá, je bohatý váš model :). Zpravidla se jedná o Domain Model, Business logiku, nebo cokoli jiného, co má na starosti ověřování obchodních pravidel, persistenci a získávání dat. Pro jednoduchost stačí vygenerovat Entity podle DB schématu pomocí ActiveRecord Generatoru nebo naopak vytvořit model a z něj vygenerovat schema.

[ActiveRecord]
public class User : ActiveRecordBase {
  [PrimaryKey] public int Id { get; set; }
  [Property] public string Name { get; set; }
  ...
}

Pro zjednodušení napsáno v C# 3.0 :) ActiveRecord plně využívá atributů k popisu schematu. Dědění třídy ActiveRecordBase není nutností, pro začátek stačí vědět, že nám přidává k entitě spoustu metod pro databázový přístup. Vhodnější pravděpodobně bude využít interface IRepository<T> z projektu Rhino.Commons, který využívá Repository pattern.

View

View jsou obvykle soubory obsahující kusy HTML kódu a prezentační logiky. K zapouzdření prezentační logiky lze využít tzv. View komponent (obdoba UserControls, ale většinou mnohem obecnější). Existují tu i layouty, což je obdoba MasterPages.

<html>
  <head>
    <title>Layout</title>
  </head>
  <body>
    ${ChildOutput}
    <p class="footer">Společná patička.</p>
  </body>
</html>

Takto vypadá velice zjednodušený layout. ${ChildOutput} bude nahrazen obsahem jednotlivých view.

Controler

Kontroler spojuje svět View se světem Modelu. Řídí činnost view mění stavy Modelu. Je to to, co dělá aplikaci aplikací.

[Scaffolding(typeof(User))]
public class UsersController : Controller {
}

Teď když zadáme něco jako http://localhost:12345/users/new.rails tak dostaneme formulář pro zadávání nových uživatelů. (V případě, že doimplementujeme třídu User, aby měla všechny potřebné vlastnosti).

Pro dnešek bych tedy ukončil první představovací článek a v příštích spotech bychom se mohli podívat na tuto zajímavou technologii trošku blíž…