Univerzita Karlova v Praze. Matematicko-fyzikální fakulta BAKALÁŘSKÁ PRÁCE. David Ligr. Systém pro správu obsahu pro základní a střední školy

Podobné dokumenty
Obsah přednášky. Představení webu ASP.NET frameworky Relační databáze Objektově-relační mapování Entity framework

PHP framework Nette. Kapitola Úvod. 1.2 Architektura Nette

INFORMAČNÍ SYSTÉMY NA WEBU

1 Webový server, instalace PHP a MySQL 13

Postup. Úvodem. Hlavní myšlenka frameworku. application. system. assets. uploads

IS pro podporu BOZP na FIT ČVUT

1. Webový server, instalace PHP a MySQL 13

Olga Rudikova 2. ročník APIN

MBI - technologická realizace modelu

Vstupní požadavky, doporučení a metodické pokyny

MATURITNÍ OTÁZKY ELEKTROTECHNIKA - POČÍTAČOVÉ SYSTÉMY 2003/2004 PROGRAMOVÉ VYBAVENÍ POČÍTAČŮ

Současný svět Projekt č. CZ.2.17/3.1.00/32038, podpořený Evropským sociálním fondem v rámci Operačního programu Praha adaptabilita

RESTful API TAMZ 1. Cvičení 11

Snadný vývoj webových aplikací s Nette. Lukáš Jelínek

Ruby on Rails. Bc. Tomáš Juřík Bc. Bára Huňková

Střední průmyslová škola elektrotechnická Praha 10, V Úžlabině 320

Maturitní otázky z předmětu PROGRAMOVÁNÍ

Střední průmyslová škola elektrotechnická Praha 10, V Úžlabině 320 M A T U R I T N Í T É M A T A P Ř E D M Ě T U

VÝUKOVÝ MATERIÁL. Bratislavská 2166, Varnsdorf, IČO: tel Číslo projektu

STŘEDNÍ ŠKOLA INFORMAČNÍCH TECHNOLOGIÍ A SOCIÁLNÍ PÉČE

Komponentově orientované webové frameworky. Jiří Stránský twitter.com/jistr

Michal Augustýn Microsoft Most Valuable Professional

Úvod do tvorby internetových aplikací

PHP PHP je skriptovací programovací jazyk dynamických internetových stránek PHP je nezávislý na platformě

Formy komunikace s knihovnami

Obsah. Zpracoval:

Základní pojmy spojené s webovým publikováním ~ malý slovníček pojmů~ C3231 Základy WWW publikování Radka Svobodová, Stanislav Geidl

VÝVOJ INTERNETOVÝCH APLIKACÍ - VIA

Platforma.NET 11.NET Framework 11 Visual Basic.NET Základní principy a syntaxe 13

1. Úvod do Ajaxu 11. Jak Ajax funguje? 13

MATLABLINK - VZDÁLENÉ OVLÁDÁNÍ A MONITOROVÁNÍ TECHNOLOGICKÝCH PROCESŮ

rychlý vývoj webových aplikací nezávislých na platformě Jiří Kosek

Aplikace pro srovna ní cen povinne ho ruc ení

KOMPONENTY APLIKACE TreeINFO. Petr Štos ECM Business Consultant

Reranking založený na metadatech

1. Webové služby. K čemu slouží? 2. RPC Web Service. 3. SOA Web Service. 4. RESTful Web services

E LEARNINGOVÁ WEBOVÁ APLIKACE PRO VÝUKU BIOMEDICÍNSKÉHO INŽENÝRSTVÍ Petr Huňka

Michal Krátký, Miroslav Beneš

Elektronická podpora výuky předmětu Komprese dat

Počítačová Podpora Studia. Přednáška 5 Úvod do html a některých souvisejících IT. Web jako platforma pro vývoj aplikací.

10 Balíčky, grafické znázornění tříd, základy zapozdření

Základy datových vazeb Silverlightu. Funkce Silverlightu 2. Podpora jazyků a technologie.net Framework

3 MOŽNÉ PŘÍSTUPY K TVORBĚ APLIKACÍ NAD SVG DOKUMENTY

Instalace a konfigurace web serveru. WA1 Martin Klíma

Seznámení s prostředím dot.net Framework

KAPITOLA 3. Architektura aplikací na frameworku Rails. V této kapitole: modely, pohledy, řadiče.

D R U P A L V O J T Ě C H K U S W O J T H A

Systém JSR představuje kompletní řešení pro webové stránky malého a středního rozsahu.

Tvorba informačních systémů

ČESKÉ VYSOKÉ UČENÍ TECHNIKÉ Fakulta elektrotechnická. Microsoft Sharepoint 2007 Workflows Průmyslové informační systémy

Část IV - Bezpečnost 21. Kapitola 19 Bezpečnostní model ASP.NET 23

Business Intelligence

Databázové aplikace pro internetové prostředí PHP úvod, základní princip, vkládání skriptu, komentáře, výpis na obrazovku

INSTALACE PRODUKTU ONTOPIA KNOWLEDGE SUITE

Maturitní projekt do IVT Pavel Doleček

TECHNICKÁ SPECIFIKACE VEŘEJNÉ ZAKÁZKY

Roční periodická zpráva projektu

Profilová část maturitní zkoušky 2017/2018

DELTA - STŘEDNÍ ŠKOLA INFORMATIKY A EKONOMIE, s.r.o. Obor informační technologie AJAX ESHOP. Maturitní projekt. Třída:

Platební systém XPAY [

Ing. Přemysl Brada, MSc., Ph.D. Ing. Martin Dostal. Katedra informatiky a výpočetní techniky, FAV, ZČU v Plzni

language="javascript">... </script>.

2015 GEOVAP, spol. s r. o. Všechna práva vyhrazena.

Replikace je proces kopírování a udržování databázových objektů, které tvoří distribuovaný databázový systém. Změny aplikované na jednu část jsou

Typy souborů ve STATISTICA. Tento článek poslouží jako přehled hlavních typů souborů v programu

Nové jazykové brány do Caché. Daniel Kutáč

TÉMATICKÝ OKRUH Softwarové inženýrství

Úvod do aplikací internetu a přehled možností při tvorbě webu

Metody tvorby ontologií a sémantický web. Martin Malčík, Rostislav Miarka

SYLABUS IT V. Jiří Kubica. Ostrava 2011

Úvodem 9. Zpětná vazba od čtenářů 10 Zdrojové kódy ke knize 10 Errata 10. Než začneme 11

ANOTACE vytvořených/inovovaných materiálů

Úvod do Web Services

Kritéria hodnocení praktické maturitní zkoušky z databázových systémů

ANOTACE nově vytvořených/inovovaných materiálů

Internetové služby isenzor

Architektury informačních systémů

Kurz je rozdělen do čtyř bloků, které je možné absolvovat i samostatně. Podmínkou pro vstup do kurzu je znalost problematiky kurzů předešlých.

IB111 Programování a algoritmizace. Programovací jazyky

UNIVERZITA PARDUBICE. Fakulta elektrotechniky a informatiky. Informační systém realitní kanceláře Jan Šimůnek

Kapitola 1: Úvod. Systém pro správu databáze (Database Management Systém DBMS) Účel databázových systémů

Specifikace požadavků. POHODA Web Interface. Verze 1.0. Datum: Autor: Ondřej Šrámek

PŘÍLOHA C Požadavky na Dokumentaci

Dobrý CMS Popis produktu a jeho rozšíření

Internet Information Services (IIS) 6.0

Informační systémy 2008/2009. Radim Farana. Obsah. Obsah předmětu. Požadavky kreditového systému. Relační datový model, Architektury databází

Tvorba informačních systémů

Webové rozhraní pro datové úložiště. Obhajoba bakalářské práce Radek Šipka, jaro 2009

Profilová část maturitní zkoušky 2013/2014

SOFISTIKOVANÉ NÁSTROJE PRO JEDNODUCHOU TVORBU PROFESIONÁLNÍCH WEBOVÝCH PREZENTACÍ

Vývoj informačních systémů. Přehled témat a úkolů

Jádrem systému je modul GSFrameWork, který je poskytovatelem zejména těchto služeb:

Stručný úvod pro programátory. Michal Kuchta

INOVACE PŘEDMĚTŮ ICT. MODUL 11: PROGRAMOVÁNÍ WEBOVÝCH APLIKLACÍ Metodika

TÉMATICKÝ OKRUH Softwarové inženýrství

EMBARCADERO TECHNOLOGIES. Jak na BYOD chytře? Možnosti zapojování různých mobilních zařízení do podnikových informačních systémů.

Architektury informačních systémů

Znalostní systém nad ontologií ve formátu Topic Maps

Dobrý FOTO Popis produktu a jeho rozšíření

Transkript:

Univerzita Karlova v Praze Matematicko-fyzikální fakulta BAKALÁŘSKÁ PRÁCE David Ligr Systém pro správu obsahu pro základní a střední školy Katedra distribuovaných a spolehlivých systémů Vedoucí bakalářské práce: Mgr. Pavel Ježek, Ph.D. Studijní program: Informatika Studijní obor: Programování Praha 2013

Děkuji panu Mgr. Pavlu Ježkovi, Ph.D. za odborné vedení mé práce, za rady a za čas, který mi během jejího vypracování věnoval.

Prohlašuji, že jsem tuto bakalářskou práci vypracoval samostatně a výhradně s použitím citovaných pramenů, literatury a dalších odborných zdrojů. Beru na vědomí, že se na moji práci vztahují práva a povinnosti vyplývající ze zákona č. 121/2000 Sb., autorského zákona v platném znění, zejména skutečnost, že Univerzita Karlova v Praze má právo na uzavření licenční smlouvy o užití této práce jako školního díla podle 60 odst. 1 autorského zákona. V Praze dne 22. 5. 2013 David Ligr

Název práce: Systém pro správu obsahu základní a střední školy Autor: David Ligr Katedra: Katedra distribuovaných a spolehlivých systémů Vedoucí bakalářské práce: Mgr. Pavel Ježek, Ph.D., Katedra distribuovaných a spolehlivých systémů Abstrakt: Pro zjednodušení správy obsahu webové aplikace existují tzv. systémy správy obsahu. Málo z těchto systémů však respektuje požadavky na ně kladené ze strany základních a středních škol. Cílem této práce je vytvoření systému správy obsahu webové aplikace, který by splňoval požadavky ze strany SpZŠ Skuteč. Výsledná aplikace je napsaná v ASP.NET MVC 3 a jazyku C#. Při návrhu aplikace byl kladen důraz na jednoduchost jejího použití a její rozšiřitelnost. Součástí práce je uvedení do problematiky vývoje webových aplikací, což zahrnuje volbu vhodného programovacího jazyka, frameworku, persistentního úložiště a dalších konceptů, které se při vývoji webových aplikací používají. Práce obsahuje vývojovou dokumentaci, která ozřejmuje význam jednotlivých modulů. Součástí práce je i uživatelská dokumentace, která popisuje způsoby správy veškerého obsahu aplikace. Klíčová slova: modulárnost, správa obsahu, webová aplikace Title: Content management system (CMS) for School Enviroment Author: David Ligr Department: Department of Distributed and Dependable Systems Supervisor: Mgr. Pavel Ježek, Ph.D., Department of Distributed and Dependable Systems Abstract: To simplify content management web application, there are so-called content management systems. Few of these systems complies with the requirements placed on them by the primary and secondary schools. The aim of this work is to create a content management system web application that would meet the requirements of the SpZŠ Skuteč. The resulting application is written in ASP.NET MVC 3 and C#. When designing an application, emphasis was placed on ease of use and its extensibility. Part of this work is the introduction to the topic of web development, which includes the selection of a suitable programming language, frameworks, persistent storage, and other concepts that are used in web development. The work includes development documentation, which highlights the importance of the individual modules. The work also includes user documentation that describes how to manage all content applications. Keywords: modularity, content management, web application

Obsah 1 Úvod... 1 1.1 Systém správy obsahu a blogovací systém... 1 1.2 Stanovené požadavky... 1 1.2.1 Lokalizace, dostupnost a nároky na ostatní software... 2 1.2.2 Poskytnuta funkčnost... 2 1.2.3 Rozšiřitelnost... 2 1.3 Motivace... 2 1.4 Cíle práce... 3 2 Analýza... 4 2.1 Existující CMS... 4 2.1.1 Bakaláři... 4 2.1.2 Škola online... 5 2.1.3 Orchard... 5 2.1.4 Shrnutí vlastností existujících CMS... 5 2.2 Programovací jazyk a platforma... 6 2.2.1 Návrhový vzor Model-View-Controller... 6 2.2.2 PHP... 7 2.2.3 Ruby... 8 2.2.4 ASP.NET... 8 2.2.5 Výběr vhodné platformy... 9 2.3 WebForms vs ASP.NET MVC... 9 2.3.1 WebForms... 9 2.3.2 ASP.NET MVC... 10 2.3.3 Výběr frameworku... 10 2.3.4 Výběr jazyka... 10 2.4 Popis Frameworku ASP.NET MVC... 11 2.4.1 Routování... 11 2.4.2 Model... 13 2.4.3 Controller... 14 2.4.4 View... 17 3 Analýza persistentního úložiště... 19 3.1 Výběr relační databáze... 19 3.2 Přístup k relační databázi... 19 3.2.1 ORM nástroje... 20 3.3 Vrstva datového přístupu... 20 3.3.1 Repositáře... 20 3.4 Definice databázového schématu... 21 3.5 Nastavení databázového schématu... 21 3.5.1 Primární klíče... 21 3.5.2 Nastavení cizích klíčů a relací... 22 3.5.3 Dědičnost... 23 3.5.4 Automaticky generované klíče a transakce... 24 4 Analýza použitých konceptů a technik... 26 4.1 Oddělení závislostí... 26

4.1.1 Způsoby vkládání závislostí... 27 4.2 Rozšiřitelnost... 28 4.2.1 Reflection... 28 4.2.2 MEF... 29 4.2.3 Ninject... 29 4.2.4 Volba... 29 4.3 Zabezpečení... 29 4.3.1 Autorizace a autentizace... 30 4.3.2 Providery... 30 4.3.3 Cross-site scripting... 31 4.3.4 Cross-site request Forgery... 32 4.3.5 SQL injection... 32 4.4 Práce s výjimkami... 32 4.4.1 Logování výjimek... 32 4.5 Testování... 33 4.5.1 Unit a Integration Testy... 33 4.5.2 Programování řízené testy... 33 4.5.3 Vkládání závislostí... 34 4.5.4 Spouštění testů... 35 4.6 Design aplikace... 36 5 Vývojová dokumentace... 38 5.1 Základní struktura zdrojových kódů... 38 5.1.1 Struktura modulu BaseModule... 39 5.1.2 Struktura modulů MediaPlugin a DocumentPlugin... 39 5.2 Struktura výsledné aplikace... 39 5.2.1 Databáze... 40 5.2.2 Konfigurační soubor web.config... 40 5.3 Princip fungování aplikace... 40 5.4 Společná řešení... 41 5.4.1 Databáze... 41 5.4.2 Použité JavaScriptové knihovny... 43 5.4.3 Značkovací jazyk a kaskádové styly... 44 5.5 BaseModule... 44 5.5.1 Projekt BaseDomain... 44 5.5.2 BaseWeb... 46 5.5.3 BaseUnitTest... 50 5.6 DocumentModule... 51 5.6.1 DocumentDomain... 51 5.6.2 DocumentWebPlugin... 52 5.6.3 DocumentUnitTest... 54 5.7 MediaModule... 54 5.7.1 MediaDomain... 54 5.7.2 MediaWebPlugin... 55 5.7.3 MediaUnitTest... 55 6 Uživatelská dokumentace... 57 6.1 Rozložení stránky ve veřejné části aplikace... 57

6.2 Rozložení stránky v backendu aplikace... 58 6.3 Popis práce s jednotlivými balíčky... 59 6.3.1 Role... 59 6.3.2 Předměty... 61 6.3.3 Pozice... 61 6.3.4 Zaměstnanci... 61 6.3.5 Aktuality... 63 6.3.6 Události... 65 6.3.7 Kategorie stránek... 65 6.3.8 Stránky... 66 6.3.9 Vzdělávací programy... 66 6.3.10 Předmětová odvětví... 66 6.3.11 Vzdělávací materiály... 66 6.3.12 Videogalerie... 67 6.3.13 Fotogalerie... 68 6.3.14 Fotografie... 68 7 Závěr... 69 7.1 Srovnání výsledku se zadáním... 69 7.2 Použití aplikace... 69 7.3 Rozšíření do budoucna... 69

1 Úvod K vývoji a správě obsahu webové aplikace je nutná znalost několika jazyků. Mezi ty nejzákladnější patří značkovací jazyk HTML, případně XHTML a jazyk CSS, který definuje způsob zobrazení webových stránek. Pro vylepšení možností interakce uživatele s webovou aplikací je třeba použít programovací jazyk k tomu vhodný. Tím může být jazyk JavaScript a s ním související technologie AJAX, která umožňuje komunikaci aplikace s webovým serverem. Ačkoliv je výše uvedený seznam jazyků spíše orientačního charakteru, poskytuje nám jasnou představu o množství znalostí, kterými musí uživatel disponovat, chce-li úspěšně vyvíjet či spravovat webovou aplikaci. Z toho důvodu vznikají systémy správy obsahu (dále jen CMS z anglického Content Management System) [1] a blogovací software (dále jen BS z anglického Blogging Software) [2]. 1.1 Systém správy obsahu a blogovací systém CMS, či BS je aplikace zjednodušující komplexní správu obsahu webové aplikace. A to díky jednotnému rozhraní, pomocí kterého mohou uživatelé spravovat obsah webové aplikace. Rozhraní je nejčastěji reprezentováno CRUD [3] operacemi, což je zkratka slov Create, Read, Edit a Delete. Toto rozhraní nám umožňuje vytváření nového záznamu. Dále úpravu, mazaní a prohlížení již existujícího záznamu. Záznamem myslíme instanci libovolného, podporovaného typu dat. Rozdíl mezi CMS a BS spočívá v poskytnuté funkcionalitě. Blogovací systémy jsou určeny ke správě obsahu blogu. Umožňují správu příspěvků a s nimi souvisejících komentářů, a to včetně podpory správy vkládaných obrázků. CMS obsahují rozsáhlejší funkcionalitu. Ta kromě funkcionality blogovacích systémů navíc obsahuje například správu datového úložiště a autorizovaných uživatelů. 1.2 Stanovené požadavky Různé organizace potřebují spravovat různé typy dat. U základních a středních škol to jsou zejména aktuality, plánované akce, fotogalerie, materiály používané při výuce, zaměstnanci, žáci, studijní výsledky, docházka, studijní programy, rozvrhy, suplování, školní jídelna a školní knihovna. Z výše uvedeného výčtu typů dat, které je potřeba u škol spravovat, a poznatků z kapitoly 1.1 vyplývá, že pro potřeby škol je vhodnější použití CMS, než BS. Výběr vhodného CMS je založen především na podpoře správy požadovaných typů dat. Dále pak na jeho vlastnostech jako jsou lokalizace, dostupnost a rozšiřitelnost. V našem případě jsme vycházeli především z požadavků stanovených ze strany Speciální základní školy Skuteč, které vyplynuly z projektu, který Speciální základní škola realizuje v rámci programu "Metody a formy práce žáků s SVP", registrační číslo CZ.1.07/1.2.29/01.0003. Činitelé SpZŠ Skuteč by chtěli

mít k dispozici CMS, který by splňoval požadavky stanovené v kapitolách 1.2.1-1.2.3. 1.2.1 Lokalizace, dostupnost a nároky na ostatní software Použitý CMS by měl obsahovat českou lokalizaci, tak aby obsah mohl být spravován i vybranými žáky nemajícími potřebné znalosti cizích jazyků. CMS by měl být dostupný pomocí protokolu HTTP a to bez nutnosti instalace jakéhokoliv softwaru na počítače, z nichž má být používán. CMS by měl fungovat na počítači, serveru spravovaném třetí osobou. To z toho důvodu, že zaměstnanci školy nemají znalosti potřebné ke konfiguraci počítačů a serverů. 1.2.2 Poskytnuta funkčnost Použitím CMS by se měly eliminovat nároky kladené na uživatele, kteří mají obsah spravovat. Těmi jsou myšleny znalosti jazyků, protokolů a technologií ke správě obsahu potřebné. CMS by měl umožňovat správu zaměstnanců (včetně jejich aprobací) a žáků školy. Dále by CMS měl obsahovat správu aktualit, fotogalerií, videogalerií, jejíž součástí by měla být možnost definice vazby mezi záznamy těchto typů dat, která by umožnila procházení souvisejících záznamů. Pro správu těchto typů dat by měl být integrován textový editor a správce souborů. U správy fotogalerií by měla být možnost dávkového nahrávání fotografií, tak aby uživatel nemusel vkládat fotografie po jedné. Součástí CMS by měla být správa plánovacího kalendáře, kde záznamy tohoto kalendáře mohou být vázány na výše zmíněné aktuality. Uložené události by se měly na stránkách zobrazovat v přehlednější formě, než je prostý seznam. V poslední řadě, by měl CMS umožňovat správu úložiště vzdělávacích materiálů libovolného formátu s možností filtrace spravovaných záznamů dle předmětů, předmětových odvětví, vzdělávacích programů, ročníků a autorů. U fotografií a vzdělávacích materiálů by měl CMS informovat uživatele o průběhu načítání vkládaných dat. CMS by měl umožňovat správu různých typů dat v závislosti na konkrétním uživateli a jeho oprávněních. Přičemž všechny záznamy veřejného charakteru by měly být přístupné veřejnosti na webu školy. 1.2.3 Rozšiřitelnost Činitelé SpZŠ Skuteč v době stanovení požadavků nedokázali zcela přesně definovat veškeré datové typy, které budou chtít v rámci aplikace spravovat. Kvůli tomu by mělo být možné CMS rozšířit o nově požadovanou funkcionalitu. 1.3 Motivace V době zadání práce existovala na internetu řada volně dostupných i komerčních CMS, těmi jsou například Bakaláři [http://www.bakalari.cz/], 2

Škola online [http://www.skolaonline.cz/] a Orchard [http://www.orchardproject.net/]. Existující CMS neodpovídají stanoveným požadavkům z toho důvodu, že se buď jedná o CMS cílené na správu agendy školy, které však neobsahují požadovanou prezentační funkčnost. Anebo se jedná o obecné CMS poskytující bohatou prezentační funkčnost, ale neobsahující správu agendy školy. Díky požadavkům ze strany SpZŠ Skuteč na typy spravovaných dat, které budou do jisté míry korespondovat s požadavky ostatních škol, a rozšiřitelnost aplikace, by v případě vhodné návrhu bylo možné poskytování více verzí výsledného CMS. Jednotlivé verze by se od sebe lišily v obsažené funkcionalitě. To by umožňovalo uplatnění CMS i ve školách s podobnými požadavky. 1.4 Cíle práce Cílem práce je vytvořit aplikaci, která bude respektovat požadavky SpZŠ Skuteč. Aplikace bude splňovat následující kritéria: 1) Webová aplikace 2) Česká lokalizace 3) Rozšiřitelnost 4) Funkcionalita pro správu i prezentaci obsahu 5) Správa uživatelů a jejich rolí 6) Integrace textového editoru a správce souborů 7) Asynchronní zpracování potencionálně dlouhých požadavků (načítání dat na server) 8) Zabezpečení 3

2 Analýza V případě, že potřebujeme novou aplikaci, je první věc, kterou musíme udělat, analýza nároků kladených na aplikaci. Podle těchto nároků se poté rozhodneme pro použití již existující aplikace, případně pro vývoj aplikace nové. Při vývoji nové aplikace si musíme vybrat prostředky k tomu vhodné, mezi ty patří např. programovací jazyk, framework a persistentní úložiště. V kapitole 2.1 se zaměříme na již existující CMS, podíváme se na jejich vlastnosti a vysvětlíme, proč nevyhovují stanoveným požadavkům. Při vývoji webových aplikací si můžeme vybrat programovací jazyk, v němž chceme aplikaci implementovat. Nejčastěji používané programovací jazyky k vývoji webových aplikací včetně frameworků v těchto jazycích psaných rozebereme v kapitolách 2.2-2.4. Poznamenejme, že použití frameworků zjednodušuje vývoj aplikace, neboť frameworky přidávají další prostředky vhodné pro vývoj konkrétního typu aplikací. Zmíněnými prostředky mohou být například implementace funkcí a definice struktury aplikace. Jelikož výsledná aplikace má sloužit ke správě obsahu, je potřeba spravovaný obsah ukládat do persistentního úložiště. O volbě vhodného úložiště, jeho struktuře a způsobu komunikace s ním bude pojednávat kapitola 3. Výsledná aplikace má obsahovat pokročilou funkčnost, proto je vhodné vybrané funkční bloky zapouzdřit, tak aby je ostatní části mohly využít. Na způsoby, pomocí nichž lze funkční bloky využívat se zaměříme v kapitole 4.1. Jedním z cílů práce je rozšiřitelnost aplikace. Způsoby, kterými lze aplikaci rozšiřovat a jejich výhody a nevýhody, budou zmíněny v rámci kapitoly 4.2. Kapitola 4.3 se bude zabývat dalším cílem, kterým je zabezpečení aplikace a to jak v rámci omezení přístupu, tak ochraně proti útokům ze strany hackerů. Při běhu webových aplikací může dojít k chybovým situacím. A proto se v podkapitole 4.4 zaměříme na možnosti reakce na výskyt chybových situací. Webové aplikace obsahují rozsáhlou funkcionalitu. K ověření její korektnosti před nasazením do ostrého provozu slouží testování. Na způsoby testování aplikací se podíváme v kapitole 4.5. V kapitole 4.6 bude probrán design aplikace, který bude vycházet z dříve provedené analýzy. 2.1 Existující CMS V kapitole 1.3 byla řeč o již existujících CMS a o tom, že nesplňují všechny požadavky kladené na aplikaci, níž se tato práce zabývá. Ve zbytku této kapitoly se podíváme na nejčastěji využívané CMS určené pro základní a střední školy v České republice. A na vlastnosti jednoho open-source CMS, který v současnosti patří mezi nejvíce vyvíjené CMS. 2.1.1 Bakaláři Bakaláři [http://www.bakalari.cz/] jsou nejrozšířenější CMS určený pro základní a střední školy na území České republiky. To především kvůli obsažené funkčnosti. Ta zahrnuje správu žáků i zaměstnanců, třídní knihy, knihovny, 4

rozvrhů hodin, tematických plánů, suplování. Což je hodně nad rámec funkcionality, kterou jsme si definovali jako požadovanou. Tento CMS je tvořený především pro správu školní agendy a standardně nenabízí možnosti prezentace školy pomocí všech požadovaných typů dat, jako jsou například aktuality, fotogalerie a videogalerie. Tento nedostatek může být napraven pomocí modulů, které lze do Bakalářů vytvářet. Problém s použitím Bakalářů spočívá v kombinaci finanční náročnosti a potřeby implementace přídavných modulů. 2.1.2 Škola online Školu online [http://www.skolaonline.cz/] lze považovat za přímého konkurenta Bakalářů na českém trhu. Funkčnost tohoto CMS obsahuje oproti Bakalářům navíc správu skladu a výukových materiálů. Oproti Bakalářům má tento CMS tu nevýhodou, že do něj není možné volně přidávat moduly, které by rozšiřovaly poskytovanou funkčnost. 2.1.3 Orchard Orchard [http://www.orchardproject.net/] je open-sourcový, modulární CMS. Díky tomu, že se jedná o volně dostupný software, je na internetu dostupná již řada hotových modulů. Pokud však nenalezneme modul s požadovanou funkčností, můžeme jej sami vytvořit. A při dodržení jmenných konvencí i přidat do cílového projektu, čímž je splněn jeden z našich požadavků. Mezi nevýhody tohoto CMS lze zahrnout neúplnou českou lokalizaci a neexistenci modulů zaměřených na správu agendy základních a středních škol. Oba tyto nedostatky by šlo díky modulárnosti odstranit. 2.1.4 Shrnutí vlastností existujících CMS Z kapitoly 2.1.2 a stanovených požadavků je patrné, že kvůli chybějící funkcionalitě a nemožnosti jejího doimplementování nejde Školu online použít k prezentaci školy, což jeden ze stanovených požadavků. V případě Bakalářů, o nichž jsme psali v kapitol 2.1.1, je již situace lepší a to díky možné rozšiřitelnosti pomocí modulů. Problém, tak spočívá především ve vynaložených financích. Orchard, který byl popsán v kapitole 2.1.3, obsahuje již desítky hotových modulů, avšak málo z nich je použitelných pro účely naší aplikace. Například kvůli požadavkům na vazbu mezi aktualitami a fotogaleriemi bychom nemohli použít existující implementace, protože ty tuto vazbu neobsahují. Doimplementovávání chybějící funkcionality by bylo náročné na čas, protože nejdříve je potřeba pochopit principy, na nichž tento CMS funguje. Navíc bychom mohli u existujících modulů narazit i na opačný problém a to, že obsahují rozsáhlejší funkcionalitu, než je požadováno. Což může snižovat například uživatelskou přívětivost. Na základě faktů uvedených v této kapitole, které jsou shrnuty v tabulce 1, jsme se rozhodli pro vývoj nového CMS, a nikoliv pro doimplementování funkcionality do CMS již existujících. To i přesto, že vývoj nového CMS bude časově náročnější. 5

Bakaláři Škola online Orchard Česká lokalizace Ano Ano Částečná Rozšiřitelnost Ano Ne Ano Správa školní agendy Ano Ano Ne Prezentace veřejných dat Ne Ne Ano Tabulka 1: Vlastnosti existujících CMS 2.2 Programovací jazyk a platforma Pro vývoj webových aplikací, máme k dispozici několik programovacích jazyků. Náš výběr přitom může záležet na mnoha aspektech. Mezi ně lze zahrnout oblíbenost široké veřejnosti, podporu ze strany webhostingových serverů, existenci rozšiřujících knihoven a frameworků. V kapitole 2.2.1 si představíme základy návrhového vzoru Model-View- Controller (dále jen MVC) [4], který je v současné době používán mnoha frameworky pro tvorbu webových stránek. V kapitolách 2.2.2-2.2.4 se podíváme na jedny z nejvýznamnějších zástupců skriptovacích (PHP, Ruby) a kompilovaných (C#) jazyků. Tyto typy jazyků jsou v současné době nejčastěji využívány (dle dat dostupných na adrese http://www.w3techs.com/) pro vývoj webových aplikací. Jazyk Zastoupení k 1. 5. 2013 Server Zastoupení k 1. 5. 2013 PHP 79,2% Apache 61,8% ASP.NET 19,9% NGinx 16,4% Ruby 0,5% MS IIS 16,2% Tabulka 2: Zastoupení Tabulka 3: Zastoupení serverů programovacích jazyků 2.2.1 Návrhový vzor Model-View-Controller Návrhový vzor Model-View-Controller [4] dělí aplikaci na tři logické části, tak aby šlo jednotlivé části upravovat samostatně a aby dopad změn na ostatní části aplikace byl co nejmenší. Jednotlivými částmi jsou model, který reprezentuje business logiku, controller obsahující aplikační logiku a view definující uživatelské rozhraní. Funkčnost jednotlivých částí aplikace si lze nejlépe vysvětlit na příkladě. K tomu můžeme použít třeba aplikaci evidující denní teploty. Model by v této aplikaci držel informace o teplotě v daném čase a funkce, které chceme nad drženými daty mít. Těmi mohou v tomto případě být například nejvyšší, nejnižší a průměrná teplota v daném časovém rozmezí. View by v této aplikaci odpovídal zobrazení držených dat. Na obrázku 1 představují view nejen grafy znázorňující vývoj denních teplot, ale i přiložená tabulka. Ve zbytku této práce budeme v souvislosti s view používat i slovo pohled, což je český ekvivalent pro view. 6

Obrázek 1: Různé implementace pohledu u návrhového vzoru MVC Controller by měl na starosti komunikaci s uživatelem, tou může například být vložení nové denní teploty. Controller by v takovém případě aktualizoval model a informoval pohled o tom, že došlo ke změně modelu a tudíž je potřeba, aby se pohled překreslil. Controller je ta část aplikace, která má na starosti provázání zbylých částí. View 4 2 Controller Model 3 5 Uživatel 1 Obrázek 2: Proces zpracování požadavku při použití návrhového vzoru MVC Proces zpracování požadavku při použití návrhového vzoru MVC, tak lze rozdělit do několika fází, tak jak je znázorněno na obrázku 2. Jednotlivé fáze jsou: 1. Controller přijímá požadavek od uživatele 2. Controller zasílá požadavek na aktualizaci, případně získaní dat modelu 3. Model vrací data controlleru 4. Controller předá získaná data do pohledu 5. Pohled vykreslí získaná data 2.2.2 PHP PHP [5] je dle současných statistik, které jsou uvedeny v tabulce 2, nejčastěji používaný programovací jazyk pro vývoj webových aplikací. Ke spuštění aplikace napsané pomocí jazyka PHP je postačující přítomnost webového serveru Apache [6]. V případě potřeby persistentního úložiště se nejčastěji využívá databázový server MySQL [7]. Přičemž oba tyto servery jsou multiplatformní a svobodně šiřitelné. Díky tomu lze aplikace napsané pomocí PHP provozovat na více než polovině komerčních i volně dostupných webhostingových serverů. Dle dostupných statistik, viz tabulka 3, tvoří Apache 61% všech používaných serverů. To je jistě jedna z hlavních výhod psaní 7

webových aplikací právě pomocí PHP. Mezi další výhody PHP patří i existence řady knihoven pro zpracování textu, grafiky, práci se soubory, které jsou součástí jazyka. Kromě knihoven zaměřených na správu dat existují v PHP i knihovny podporující protokoly rodiny TCP/IP. Pomocí PHP jsou implementovány i frameworky pro vývoj webových aplikací. Nejznámějším z nich Zend Framework [8], jehož vývoj je podporován ze strany vývojářů jádra PHP. Tento framework je postaven na bázi návrhového vzoru MVC. Mezi hlavní nevýhody PHP patří: nekonzistence, tedy nedodržování jmenných konvencí v rámci různých skupin funkcí ačkoliv PHP obsahuje mechanismus výjimek, který standardně slouží k informování o výskytu chybového stavu při běhu aplikace, tak funkce jazyka informují o chybových stavech pomocí návratových hodnot, což činí ošetření chybových stavů o dost náročnější dynamická typovost jazyka, kdy typ není vázán na proměnnou, ale na hodnotu, díky čemuž můžeme nevědomě měnit typ proměnných, což vede například k neočekávaným výsledkům v rámci porovnání hodnot dvou různých datových typů 2.2.3 Ruby Ruby [9] je v současné době jeden z 3 (PHP, Perl, Ruby) nejvíce využívaných skriptovacích jazyků používaných k vývoji webových aplikací. Pro psaní webových aplikací v Ruby existuje především open-sourcový framework Ruby on Rails [10]. Stejně jako Zend Framework v případě PHP i Ruby on Rails je postaven na bázi návrhového vzoru MVC. Tento framework obsahuje řadu funkcí pro snadné generování HTML, formátování dat a práci s AJAXem. Ruby on Rails jsou na tom dobře i ze strany webhostingových serverů, kde jsou podporovány serverem NGinx [11]. NGinx tvoří 16% všech dostupných serverů. Dříve bylo možné za jeden z nedostatků považovat nedostatečnou dokumentaci. To již dnes nelze říci, a tak můžeme Ruby on Rails považovat za jednoho z nejvhodnějších kandidátu pro vývoj webových aplikací. 2.2.4 ASP.NET ASP.NET [12] je nástupcem ASP [13]. Od ASP se však ASP.NET diametrálně liší. Tato technologie na rozdíl od ASP funguje na platformě.net a zdrojový kód aplikace je kompilován do Common Intermediate Language (CIL) [14]. Díky mezikroku s použitím CIL mohou programátoři pro psaní logiky aplikace využít jakýkoliv z jazyků podporovaných platformou.net. Mezi ty patří například jazyky Visual Basic, C#, C++ a IronRuby. Protože je zdrojový kód aplikace kompilován, tak mají aplikace napsané v ASP.NET potencionálně lepší výkon, než aplikace psané pomocí skriptovacích jazyků jako jsou PHP a Ruby. Mezi hlavní výhody ASP.NET patří kromě zmíněné možnosti výběru programovacího jazyka i kompletní online dokumentace a také podpora 8

vytváření webových aplikací ve Visual Studiu, které uživatelům poskytuje komfort v podobě Intelli-Sense [15], vestavěného debuggeru a dalších nástrojů. Pro psaní webových aplikací v ASP.NET se v současné době používají především frameworky WebForms [16] a ASP.NET MVC [17]. Při použití obou těchto frameworků máme možnost výběru vhodného programovacího jazyka. Hostovat aplikace napsané pomocí ASP.NET lze primárně na serveru IIS (Internet Information Services) [18], který tvoří 16% všech dostupných serverů. Existuje i implementace platformy Mono [19], která obsahuje prostředky k provozování podmnožiny aplikací, které lze provozovat na serveru IIS. O podmnožinu se jedná proto, že součástí této implementace nejsou nejnovější verze ASP.NET. V případě, že bychom si vystačili s implementovanými prostředky (ASP.NET 2), můžeme pomocí platformy Mono provozovat aplikaci i na serveru Apache. 2.2.5 Výběr vhodné platformy Pro použití ASP.NET jsme se rozhodli především proto, že při použití této technologie lze použít i ostatní frameworky psané pro.net. Díky tomu lze napsat kvalitní aplikaci s podstatně menším úsilím, než kdybychom měli veškerou funkcionalitu s aplikací spojenou implementovat sami. Dále proto, že se zdrojový kód kompiluje, a tak je provedená alespoň typová kontrola již v době překladu aplikace. 2.3 WebForms vs ASP.NET MVC V kapitole 2.2 jsme se rozhodli pro použití technologie ASP.NET k implementaci naší aplikace. Zbývá si vybrat programovací jazyk a zanalyzovat vlastnosti poskytovaných frameworků, kterými jsou WebForms a ASP.NET MVC, a na jejich základě provést výběr frameworku, který bude v aplikaci použit. 2.3.1 WebForms Framework Web Forms vychází z myšlenky, že webové aplikace fungují stejným způsobem jako ty desktopové. To znamená, že výsledná stránka je složena z několika visuálních ovládacích prvků, které mají oddělenou logiku neboli code-behind, od vykreslení. Každý takový prvek se nachází v jednom z množiny možných stavů a jsou na něj vázány události. Pomocí těchto událostí komunikuje uživatel s aplikací. Především první ze zmíněných myšlenek se ovšem neslučuje s podstatou webových aplikací, kde komunikace mezi klientem a serverem je bezstavová. Proto se u WebForms pro ukládání aktuálního stavu aplikace používá mechanismus ViewState. Tento mechanismus funguje na principu zasílání aktuálních hodnot určených prvků formou skrytých, šifrovaných dat. Podoba přijatých dat je vidět na obrázku 3. Tato data se při každém dotazu posílají na server a z něj, případně s provedenými změnami, zpátky k uživateli. To může vést v krajních případech k přenášení několika stovek nadbytečných kb dat při každém dotazu. Přičemž přenos takového množství dat může být pro uživatele frustrující v případě pomalého připojení k internetu. 9

Dalšími nevýhodami tohoto frameworku jsou časté problémy s propojením událostí vznikajících u klienta s jejich obsluhou na straně serveru a omezená kontrola nad HTML kódem, který je generován přímo z komponent. Obrázek 3: ViewState data vložená do stránky odesílané uživateli Použití frameworku Web Forms je tak vhodné v případě, kdy chceme vytvořit jednodušší webovou aplikaci. Pomocí WebForms to dokážeme v krátkém čase a s malým vynaloženým úsilím. Stačí nám vhodně použít předdefinované visuální ovládací prvky. 2.3.2 ASP.NET MVC Název tohoto frameworku je odvozen z návrhového vzoru MVC [4], jehož základní koncept byl popsán v kapitole 2.2.1. Aplikace vytvořená pomocí ASP.NET MVC odpovídá více způsobu komunikace v Internetu, než je tomu v případě WebForms. V rámci životního cyklu dotazu si není třeba pamatovat aktuální hodnoty vybraných prvků. Jediné, co je potřeba, je zaslat požadavek na server a vykreslit odpověď zaslanou serverem. Stejně jako v případě WebForms dochází u ASP.NET MVC k oddělení logiky od způsoby vykreslení. V ASP.NET je toto oddělení dokonce jemnější, jelikož logika se dále dělí na aplikační a business. Aplikační logika definuje způsob fungování aplikace, tedy například reakce na uživatelské požadavky a komunikaci mezi jednotlivými částmi aplikace. Business logika definuje objekty z reálného světa, s kterými chceme v aplikace pracovat, a komunikaci mezi nimi. Business logika se u návrhového vzoru MVC definuje pouze na jednom místě, což lze provést díky jejímu oddělení od ostatních částí aplikace. 2.3.3 Výběr frameworku Výsledná aplikace má sloužit ke správě obsahu. Kontrolu konzistence obsahu aplikace obsahuje business logika, jejíž význam byl stručně popsán v kapitole 2.3.2. Pro ASP.NET MVC jsme se rozhodli především kvůli rozdělení aplikace do více částí, což činí její celkový návrh čitelnější a v případě potřeby lépe upravovatelný. 2.3.4 Výběr jazyka Jak bylo řečeno v kapitole 2.2.4 logiku webových aplikací v ASP.NET MVC lze psát pomocí více jazyků. To se netýká kódu ve view, kde je použitý jazyk závislý na vybraném view enginu. View engine je ta část aplikace, která hledá odpovídající pohledy a provádí jejich vykreslení. View enginy, které jsou implicitně podporovány Visual Studiem při tvorbě webové aplikace pomocí ASP.NET MVC, umožňují použití jazyků C# a Visual Basic. 10

Z důvodu zachování jazykové konzistence v celé aplikaci, jsme se rozhodli pro použití jednoho z těchto jazyků. Konkrétně pro jazyk C#, jehož výhoda při vývoji webových aplikací oproti jazyku Visual Basicu spočívá ve skutečnosti, že většina literatury pro danou tématiku obsahuje kódy psané právě v jazyce C#. Dalším faktorem pro výběr C# byla autorova pokročilá znalost tohoto jazyka. 2.4 Popis Frameworku ASP.NET MVC O rozdělení aplikace psané pomocí návrhového vzoru MVC na části jsme se bavili v kapitole 2.2.1. Toto rozdělení existuje i u webových aplikací, kde tak máme například oddělen HTML kód od aplikační a business logiky, tak jak bylo uvedeno v kapitole 2.3.2. U webových aplikací je součástí aplikace napsané pomocí návrhového vzoru MVC ještě část, která má na starosti tzv. routování. Každá z částí aplikace psané pomocí návrhového vzoru MVC by měla mít přesně určenou funkcionalitu, která by se neměla překrývat s funkcionalitou ostatních částí. Toto rozdělení se nazývá oddělení zodpovědností (SoC, což je zkratka anglických slov Separation of Concerns) [17]. V podkapitolách 2.4.1-2.4.4 se zaměříme na popis jednotlivých částí návrhového vzoru MVC a na technologie a frameworky, které můžeme využít pro zjednodušení vývoje výsledné aplikace. 2.4.1 Routování U webových aplikací, které jsou psané pomocí návrhového vzoru MVC implicitně neexistuje vazba mezi adresou stránky, na kterou uživatel posílá svůj požadavek, a souborem na disku, který by tomuto požadavku odpovídal. U návrhového vzoru MVC odpovídá adrese stránky veřejná metoda vhodného controlleru. Tento princip zpracování požadavku platí i v případě ASP.NET MVC. Převod adresy stránky na název controlleru a jeho metody se častěji nazývá směrování, nebo také routing, a má ho na starosti směrovací systém. Směrování funguje tak, že směrovací systém projde tabulka všech směrovacích pravidel, které byly ve směrovacím systému zaregistrovány, a vrátí hodnoty (název controlleru a jeho veřejné metody) odpovídající první shodě. Proces hledání první shody je znázorněn na obrázku 4. Z toho plyne fakt, že záleží na pořadí, v kterém jsou směrovací pravidla předložena směrovacímu systému. Tabulka směrovacích pravidel je slovník indexovaný regulárními výrazy. Adresa požadavku tedy odpovídá danému směrovacímu pravidlu právě tehdy, když matchuje daný regulární výraz. 11

Přichozí požadavek Vyhodnocení požadavku proti routovacímu pravidlu Odpovídá požadavek routovacímu pravidlu Ne Ano Požadavek je mapován na metodu Controlleru Ano Existuje další routovací pravidlo Ne Požadavek je mapován na soubor Obrázek 4: Proces zpracování adresy požadavku vůči směrovacím pravidlům V případě, že nechceme směrovat konkrétní adresu na metodu controlleru, stačí nám do tabulky směrovacích pravidel zaregistrovat pravidlo, které říká, že v tomto případě chceme zrušit procházení směrovacích pravidel. Díky tomu není nalezeno vhodné směrovací pravidlo a požadavek je směrován na soubor s odpovídající adresou. Až v případě, že takový soubor neexistuje, je vrácena chyba 404, tedy soubor nenalezen. Generováni URL Kromě směrování příchozích požadavků na metody controllerů má směrovací systém na starosti i generování adres pomocí tzv. html helperů. O nich pro tuto chvíli poznamenejme, že to jsou metody používané pro generování často opakujícího se HTML kódu. Proces generování je také založen na hledání první shody v tabulce směrovacích pravidel. Dá se však použít i jeden parametr navíc, který obsahuje jméno směrovacích pravidla, které se má použít. Zmíněné generování adres má tu výhodu, že při změně směrovacích pravidel dojde k automatické změně generovaných adres tak, aby pořád odpovídaly definovaným pravidlům. Pokud bychom adresy psali manuálně, je v případě změny směrovacích pravidel, nutné provést i změny příslušných adres. Přičemž toto řešení by bylo nejen časově náročnější, ale i náchylné na chyby. V případě, že chceme vygenerovat adresu, nemusíme zadávat všechny části, které jí definují. Směrovací systém automaticky dosazuje hodnoty definující aktuální požadavek. To v případě, že tyto hodnoty v adrese předchází první explicitně uvedené hodnotě. Proto nám pro vygenerování URL odpovídající jiné metodě aktuálního controlleru stačí zadat pouze název požadované metody a směrovací systém dosadí ostatní části potřebné k vygenerování adresy za nás. Formát URL Webové vyhledávače řadí výsledky hledání i podle URL stránky, na které je hledaný text dostupný. URL generované pomocí námi definovaných směrovacích pravidel by proto měly splňovat následující nároky: být čitelné pro uživatele popisovat obsah stránky a ne implementační detaily obsahovat nadpis stránky a ne její číselnou reprezentací, případně obsahovat obě hodnoty 12

neobsahovat informace o typech souborů tvořit hierarchickou strukturu být konzistentní skrz celou aplikaci 2.4.2 Model V našem případě, kdy vyvíjíme aplikaci ke správě obsahu, je model nejdůležitější částí návrhového MVC. To kvůli tomu, že v návrhovém vzoru MVC je obsah aplikace reprezentován právě modelem. Návrh modelu můžeme rozdělit do dvou částí: 1. identifikujeme entity reálného světa, se kterými chceme v rámci aplikace pracovat 2. převedeme vlastnosti, akce a pravidla spojené s entitami z reálného světa do softwarové reprezentace Množinu všech entit nazýváme doména. Softwarová reprezentace všech entit se nazývá doménový model. Jedná se o množinu typů (třídy, struktury, enumy atd.) daného programovacího jazyka, v našem případě jazyka C#. Prvkům doménového modelu se říká doménové typy. Akce spojené s daným doménovým typem jsou reprezentovány metodami v něm obsaženými. Mluvíme-li o doménovém objektu, tak máme na mysli instanci určitého doménového typu. Díky definici vlastností a metod doménových typů se říká, že model obsahuje business logiku aplikace. Jediný způsob, jak v návrhovém vzoru MVC komunikovat s modelem je pomocí volání veřejných metod, případně vlastností, příslušných doménových typů z controlleru, kterému jsou vracena data formou návratových hodnot. Díky tomuto jedinému způsobu komunikace nemusí mít a správně by neměl mít model žádné znalosti ostatních částí návrhového vzoru, což je v souladu s principem oddělení závislostí. ASP.NET MVC a poskytnutá infrastruktura ASP.NET MVC obsahuje 3 součásti, které nám zjednodušují práci s doménovým modelem: 1. Model-binding je na konvencích založený princip získávání dat. Při použití model-bindingu metody, které jsou přístupné pomocí protokolu HTTP, nemusí mít jako své parametry pouze primitivní datové typy, které jsou atributy daného datového typů. Naopak mohou mít jako parametry složitější datové typy. Model-binding zajistí, že veřejné proměnné uvedeného datového typu jsou automaticky naplněny přijatými daty. Pokud má metoda přijímat celou kolekci určitého datového typu, je potřeba jednotlivé instance indexovat tak, jak jsme na to zvyklí u C# polí. O zbytek se model-binding postará sám. 2. Modelová metadata nám formou atributů umožňují přidat k položkám datového typu dodatečné informace. Například pro nás lépe pochopitelný název dané proměnné, popis jejího zobrazení atd. ASP.NET MVC obsahuje základní sadu atributů. Tato sada je rozšiřitelná o námi definované atributy, což jsou třídy poděděné od ValidationAttribute. 13

3. Validace má za úkol kontrolu konzistence datového typu na základě uvedených pravidel. Pravidla, která mají být aplikována na daný atribut datového typu, mohou být vyjádřena pomocí modelových metadat, to včetně námi definovaných chybových hlášek, tak jak je vidět na obrázku 5. Na něm mají atributy modelu přiřazeny modelová metadata definující česká jména atributů a validační podmínky, které atributy musí splňovat. Dále na obrázku 5 pomocí modelových metadat definujeme primární klíč třídy Person. Pokud nelze validační logiku vyjádřit pomocí modelových metadat, je možné datový typ podědit od IValidatableObject. Toto rozhraní nám definuje metodu Validate, do níž se vkládá požadovaná validační logika. Zmíněný postup je vhodný v případě, kdy například potřebujeme zkontrolovat hodnotu atributu proti hodnotám stejného atributu ostatních doménových objektů. Metoda Validate i validace založená na modelových metadatech se provádí vždy při model-bindingu. Nespornou výhodou je možnost použití obou přístupu zároveň. Způsob validace pomocí modelových dat i podědění od IValidatable objektu splňuje princip DRY (zkratka anglických slov Don t Repeat Yourself) [17]. Základní myšlenka tohoto principu spočívá v neopakování kódu. To je zajištěno díky definici požadované funkčnosti pouze na jednom místě a ne distribuovaně po celé aplikaci. Princip DRY je jedním ze základních principů vývoje pomocí návrhového vzoru MVC. Mezi hlavní přínosy principu DRY patří zlepšení čitelnosti a složitosti budoucí modifikace výsledného kódu. Například při potřebě změny validačních podmínek daného doménového typu, postačí změnit validační atributy navázané na jeho atributy, případně kód metody Validate. Obrázek 5: Model, jehož atributy mají přiřazená modelová metadata 2.4.3 Controller Controller obsahuje aplikační logiku, která říká, jak se má požadavek zpracovat. Neobsahuje business logiku, která je součástí modelu, a funkcionalitu spojenou s vykreslováním uživatelského rozhraní, kterou má na starosti pohled. Funkčnost controlleru zahrnuje: přijmutí všech požadavku od uživatele případné provedení potřebných operací nad doménovým objektem, tyto operace controller provádí pomocí reference na objekt reprezentující model 14

vrácení odpovědi uživateli, odpověď může být reprezentována například vykreslením příslušného pohledu ASP.NET MVC nás nikterak neomezuje ve způsobu, kterým aplikace informuje uživatele o zpracování požadavku. Způsob, kterým aplikace informuje uživatele o zpracování požadavku, závisí na návratovém typu dané metody controlleru. Nejčastěji používanými návratovými typy jsou ViewResult, RedirectToRouteResult a JsonResult. Stejně jako v případě doménových typů někdy potřebujeme definovat dodatečné informace u metod controlleru. K tomu se stejně jako v případě doménových typů používají atributy. Návratové typy ViewResult je nejvíce využívaným návratovým typem. Při použití tohoto návratového typu se uživateli vykresluje pohled s daty, které mu controller předá. ViewResult se používá v případě, že požadavek má pouze zobrazit požadovaná data a nevadí, že se překreslí celá stránka. Dalším používaným typem je RedirectToRouteResult. Ten se používá především u akcí provádějících změny nad doménovým objektem tak, aby nebylo možné jejich opakované provádění pomocí refreshe stránky. Posledním hojně využívaným návratovým typem je JsonResult. Pomocí něj se vracejí data ve formátu Json [20].Tento návratový typ se nejvíce využívá v případě, kdy chceme zaktualizovat pouze obsah části stránky bez nutnosti jejího překreslení. Návratový typ JsonResult souvisí především s asynchronním zpracováním, které je možné díky frameworku jquery a technologii AJAX. Atributy metod Při vývoji webových aplikací se často stává, že na jedné adrese chceme mít dostupných více metod. V tom případě je výběr vhodné metody závislý například na způsobu, jakým je požadavek proveden. Proto v ASP.NET MVC existují atributy HttpPost, HttpGet a další, v našem případě nevyužívané atributy. Metoda s atributem HttpPost je volaná pouze v případě, že dotaz na odpovídající adresu je veden formou POST dotazu. POST dotaz se používá v případě, že dotaz mění stav aplikace. Dále při provádění změn nad doménovým modelem nebo při posílání důvěrných dat, tak aby odeslaná data nebyla součástí query stringu [21]. Query string je součástí adresy dotazu a data v něm obsažená jsou tak pro uživatele čitelná. Požadavek vedený formou GET dotazu by tak měl být použit pro metody, jejichž jedinou funkčností je získání požadovaných dat. V ASP.NET MVC jsou implicitně všechny veřejné metody controlleru volatelné pomocí protokolu HTTP. Tento přístup není vždy vhodný, to platí zejména pro metody definující tzv. komponenty, mezi ně například patří menu webové stránky. Způsob, jak zrušit implicitní chování je spojen s použitím atributů ChildActionOnly a NonAction. Atributem ChildActionOnly se anotují ty metody, které mají být volatelné jen z libovolného pohledu. NonAction atribut je méně restriktivní. Jeho užitím zamezíme volání metody jako akce controlleru, jinak lze ale tuto metodu volat libovolně. Častým scénářem je zpřístupnění metody, případně celé třídy, jen uživatelům splňujícím definované podmínky. V případě, že se dané podmínky týkají 15

prověření uživatele a jeho rolí, se tato kontrola nazývá autorizace. Díky rolím nemusíme přístup k dané funkcionalitě omezit na dané uživatele, ale na skupiny uživatel. Uživatele v těchto skupinách poté můžeme spravovat za běhu aplikace. Vhodnějším a také čitelnějším způsobem, než testování daných podmínek na začátku metody, případě celé třídy v jejím konstruktoru, nebo jiné vybrané metodě, je použití atributu Authorize, jehož použití je zobrazeno na obrázku 6. Kód znázorněné metody je přístupný pouze autorizovaným uživatelům v případě, že dotaz na odpovídající adresu je veden formou POST dotazu. Díky anotaci metody, třídy atributem Authorize se automaticky provede autorizace uživatele před vstupem do daného funkčního bloku. Obrázek 6: Metoda zpracovávající pouze požadavky vedené formou POST, která je přístupná pouze autorizovaným uživatelům Asynchronní zpracování Jedním z cílů práce stanovených v kapitole 1.4 je i asynchronní zpracování. ASP.NET MVC obsahuje koncept asynchronních controllerů a metod [17]. Asynchronní metody jsou používány v případě, že jejich funkčnost závisí na jiné komponentě, která je například dostupná na Internetu. Při běžném provádění by bylo vykonávající vlákno blokováno do doby, než by volaná komponenta vrátila výsledek. Při použití asynchronního zpracování je vykonávající vlákno uvolněno. Pro dokončení zpracování požadavku je přiřazeno libovolné vlákno až ve chvíli, kdy volaná komponenta vrátí výsledek. Takovýto způsob zpracování potencionálně zvyšuje výkon celé aplikace. Kód asynchronní metody je reprezentován dvojicí metod, kde první metoda zavolá potřebné služby, jejich počet je reprezentován počítadlem. Ve chvíli, kdy je hodnota počítadla rovna nule je spuštěná druhá metoda, která dostává výsledky služeb spuštěných v první metodě jako své parametry. Díky tomu není blokováno volající vlákno po dobu provádění vzdálených služeb, tak jak by tomu bylo při normálním zpracování. Pokud chceme měnit jen obsah nějaké komponenty, tak můžeme využít funkcionalitu frameworku jquery [22], který je defaultně součástí aplikace vytvářené v ASP.NET MVC. jquery obsahuje metodu getjson, pomocí níž můžeme poslat asynchronní dotaz na server a po jeho provedení zpracovat data vrácená ve formátu JSON [20]. Tento přístup je v aplikaci uplatněn například pro získání událostí školy. Ty jsou zobrazeny v kalendáři zobrazujícím události daného měsíce. Předchozí koncepty nejde použít v případě, že chceme na server uploadovat data od uživatele. V prvním případě není časově náročná operace zpracování uploadovaných dat na serveru, ale jejich upload, takže by nám asynchronní metody nepomohly. Druhý přístup nejde použít z toho důvodu, že framework jquery defaultně neobsahuje funkcionalitu pro uploadování souborů. K tomu, abychom uživatelům poskytli komfort v podobě asynchronního nahrávání dat na server spolu s informací o aktuálním průběhu, můžeme použít 16

například knihovnu jquery Form Plugin[22]. Ta je použita v aplikaci k načítání vzdělávacích materiálů a fotografií. 2.4.4 View V pohledu by, dle definice návrhového vzoru, mělo docházet pouze k vykreslování dat, které mu jsou předány z controlleru. K vykreslování získaných dat se používá tzv. view engine. ASP.NET MVC obsahuje od verze 3 dva základní nástroje určené k vykreslování. Novějším z nich je Razor, který má stručnější a přehlednější syntaxi. Druhým dříve hojně používaným view enginem je ASPX. ASPX se dále používá především v případě, že chceme zajistit kompatibilitu se staršími projekty. V rámci aplikace je použit view engine Razor. To z důvodu jeho lepších vlastností a jeho rychlejšího osvojení. Předávání dat z controlleru do pohledu Data mohou být do pohledu z controlleru předávána více způsoby. Prvním a ne zrovna vhodným způsobem je jejich vkládání do datového slovníku ViewData. Použití datového slovníku s sebou nese problémy spojené s konzistencí vykreslovaných dat, jelikož při překladu není možné zjistit, jestli slovník obsahuje daný klíč a tedy i data ním adresovaná. Pokus o vykreslení neexistujících dat, pak končí výjimkou. Dále je použití datového slovníku nevhodné z důvodu potřeby explicitního typování, jelikož slovník drží reference na instance třídy object. Pro vypsání hodnot proměnných je potřeba v pohledu instance přetypovat na původní datový typ. Od ASP.NET MVC 3 je možné použit objekt ViewBag, který ukazuje na ta samá data, jako dříve zmíněný slovník ViewData, jen se pomocí něj k nim přistupuje jako k atributům tohoto objektu. Preferovaným způsobem, jak předávat data z controlleru do pohledu je použití tzv. silně typových pohledů (anglicky Strongly typed views). Tehdy má pohled explicitně definovaný typ dat, jež mu jsou předávána. To eliminuje nedostatky spojené s předáváním dat pomocí datového slovníku. Navíc v případě silně typových pohledů funguje správně i Intelli-sensi, což značně zjednodušuje a zrychluje vývoj aplikace. Html helpers a Partial Views Při vývoji webových aplikací je často potřeba opakovaně vykreslovat určitý HTML kód. Pokud bychom tento problém řešili pomocí opakování daného bloku kódu, tak by se náš kód stal špatně čitelný a náchylný k chybám. Proto existují v ASP.NET MVC tzv. html helpery [17], pomocí nichž je možné opakovaně vykreslovat tentýž kód. Jejich použitím se držíme i principu DRY, protože danou funkcionalitu máme definovanou pouze na jednom místě. Html helpery se používají k definici vykreslení atributů daných tříd. V ASP.NET MVC je možné definování vlastních html helperů a to pomocí vytvoření extension metody třídy HtmlHelper. Partial views řeší stejný problém jako html helpery. Od html helperů se liší především způsobem použití, kdy partial views jsou používány k vykreslení větších bloků HTML kódu, než je tomu v případě html helperů. 17

Editor a Display Templates ASP.NET MVC obsahuje mechanismus templatů [17], neboli šablon, pomocí nichž je možné automatické vykreslení vhodných HTML tagů pro atributy doménového objektu. Výběr vhodné šablony probíhá na základě datového typu atributu a definovaných metadat. Pokud atributu změníme datový typ, či přiřazená metadata, tak se změna automaticky promítne i do HTML kódu, kde se vygeneruje odlišný HTML tag. Často se však stává, že chceme v rámci výsledné stránky pomocí šablon vykreslit i hodnotu nějakého neprimitivního typu. V tom případě si můžeme definovat vlastní šablonu, sloužící jako předpis pro zobrazení daného datového typu. K tomu, aby view engine mohl používat uživatelsky definované šablony, je nutné dodržovat definované jmenné konvence. Implicitní jmenné konvence jsou popsány například v Pro ASP.NET MVC 3 Framework [17]. 18

3 Analýza persistentního úložiště Cílová aplikace má sloužit ke správě obsahu. S tím souvisí potřeba ukládání spravovaného obsahu do vhodného persistentního úložiště. Tím může být například plain-textový soubor, XML soubor nebo relační databáze. U webových aplikací jsou nejčastěji využívaným persistentním úložištěm relační databáze. Ty obsahují prostředky například k manipulaci s daty, definici vhodného formátu pro uložení dat a definici automaticky spuštěných funkcí, které mohou kontrolovat například konzistenci dat. Z důvodu jednoduší manipulace s fotografiemi a vzdělávacími materiály nebudeme tyto data ukládat do databáze, ale na disk. Videa budeme načítat ze serveru http://www.youtube.com/, tak aby bylo možné jejich streamované přehrávání. Díky tomu nám bude stačit ukládat do databáze pouze HTML tah pro vložení vybraného videa do stránky. 3.1 Výběr relační databáze ASP.NET nám žádným způsobem nediktuje konkrétní relační databázi, kterou máme v rámci aplikace použít. Nejschůdnějším řešením je využití databáze MSSQL, která je podporována na většině webhostingových serverů běžících na IIS. Pro účely vývoje poté můžeme použít Express verzi tohoto serveru, která je limitovaná v počtu použitých jader, operační paměti a velikosti na disku. Funkčnost podporovaná Express verzí tvoří podmnožinu funkčnosti plnohodnotné verze, takže nehrozí, že to co nám bude fungovat při vývoji, nebude fungovat na serveru, kde bude aplikace hostovaná. Ačkoliv je naše aplikace zaměřená na správu obsahu, který je potřeba ukládat do databáze, tak si vystačíme s běžně používanými konstrukcemi. Těmi jsou myšleny indexy a transakce. Tyto konstrukce jsou podporovány i v MSSQL Express. Pro použití databáze MSSQL v naší aplikaci mluví i fakt, že tuto databázi lze spravovat přímo z Visual Studia. 3.2 Přístup k relační databázi S použitím relační databáze k persistentnímu ukládání dat souvisí problém různé reprezentace dat v databázi a aplikaci. Zatímco v databázi je entita reprezentována pomocí jednoho či více řádků dané tabulky v aplikaci je reprezentovaná instancí dané třídy. Pokud tedy chceme pracovat s daty, která jsou uložená v databázi, musíme se nejdříve postarat o jejich převod do objektové reprezentace. Kvůli tomuto častému problému vznikly nástroje zvané ORM [23], což je zkratka za Objektově relační mapování nebo anglicky Object-relational mapping. ORM nástroje mají na starosti konverzi dat mezi relační databází a objekty použitými při objektově orientovaném programování. Pomocí ORM nástrojů nemusíme s databází komunikovat skrz zasílání námi napsaných SQL skriptů, ale voláním metod příslušných objektů. Což je způsob, 19

na který jsme zvyklí v objektovém programování. ORM nástroje samy zajistí překlad metod do SQL skriptu a jejich spuštění v databázi. Komunikace s databází pomocí námi psaných SQL skriptů není vhodná především z toho důvodu, že toto řešení je časově náročné a náchylné na chyby. Na druhou stranu máme s tímto přístupem úplnou kontrolu nad prováděnými dotazy. 3.2.1 ORM nástroje Stejně jako v případě databáze ani u volby vhodného ORM nástroje nás ASP.NET MVC nijak neomezuje ve výběru. Mezi nejpoužívanější ORM nástroje patří Entity Framework [17] a NHibernate [24]. Entity Frameworku neobsahuje veškerou funkcionalitu dostupnou u NHibernate. NHibernate umožňuje navíc například definici více druhů vazeb a způsobů generování jednoznačných identifikátorů. To je pokročilejší funkcionalita, než v cílové aplikaci potřebujeme. Mezi hlavní výhody Entity Frameworku patří online dokumentace, integrace do Visual Studia a možnost práce s entitami pomocí Linq To Entities [25]. Kde Linq to Entities je způsob dotazování se nad datovým modelem generovaným Entity Frameworkem pomocí volání metod, případně skriptů, podobným standardním SQL skriptům. A také to, že v rámci literatury použité ke studiu vytváření webových aplikací pomocí ASP.NET MVC je použit Entity Framework. Entity Framework je použit v rámci výsledné aplikace na základě zmíněných výhod. 3.3 Vrstva datového přístupu Business logika obsažená v doménových typech a ukládání, načítání těchto typů z databáze jsou navzájem nesouvisející úlohy. Protože návrhový vzor MVC staví na principu oddělení závislostí [17] je běžné definovat vrstvu, pomocí které se bude manipulovat s databází. Tato vrstva se nazývá vrstvou datového přístupu (dále jen DAL, což je zkratka anglických slov Data Access Layer) [17]. DAL je v aplikaci implementována pomocí tzv. repositářů. Slovo repositář je počeštělá forma anglického slova repository. Tato počeštěná forma je použita například v oficiální dokumentaci PHP frameworku Nette [26]. Každý z repositářů obsahuje veškerou funkcionalitu spojenou s manipulací určitého doménového typu v databázi. Se zavedením DAL souvisí změna způsobu komunikace controlleru s databází. Controller nekomunikuje přímo s databází, ale používá rozhraní definované na příslušném repositáři. 3.3.1 Repositáře Rozhraní repositářů často předepisuje pouze 4 základní operace (vytváření, editování, mazání a prohlížení) spojené s manipulací daného doménového typu v databázi. V takovém případě, je možná definice generického repositáře. Ten nám umožní obsáhnout funkčnost potřebnou pro manipulaci nad více 20

doménovými typy pomocí jedné implementace, což šetří především čas potřebný na základní zprovoznění databáze. Během vývoje se mohou objevit specifické nároky na manipulaci s daným doménovým typem. V tom případě musíme naimplementovat repositář obsahující veškerou funkcionalitu spojenou s vybraným doménovým typem. Přestože je první z uvedených přístupu méně náročný na čas potřebný k jeho implementaci, prostudovaná literatura obsahuje pouze příklady implementací repositářů určených pro manipulaci s jediným datovým typem. Tento přístup je použit i v aplikaci, kterou se zabývá tento text. 3.4 Definice databázového schématu Abychom mohli ukládat data do relační databáze, musíme nejdřív definovat strukturu odpovídajících tabulek. Bez použití nástrojů jako Entity Framework bylo nutné skript definující schéma tabulek napsat, případně naklikat v nějakém editoru. Entity Framework a další ORM nástroje přichází s přístupem nazývajícím se Code First [17]. Díky němu nám stačí definovat objekty, které chceme v databázi ukládat a ORM nástroj dané schéma vygeneruje za nás, případně i s definicí primárních a cizích klíčů. Opačným přístupem je Scheme First [27]. Tehdy Entity Framework generuje definice C# tříd na základě databázového schématu. V rámci vývoje aplikace byl použit přístup Code First kvůli rychlosti s jakou lze aplikaci pomocí tohoto přístupu vyvíjet. 3.5 Nastavení databázového schématu Výkon aplikace pracující hojně s databázi je do značné míry závislý na výkonu databáze. Proto existují tzv. normální formy, které definují pravidla zajišťující optimální využití relačních databází. Ty se týkají především schématu tabulek, tak aby neobsahovaly redundantní informace a nedocházelo k různým anomáliím. 3.5.1 Primární klíče Důležitým pojmem z oblasti databází je primární klíč. Primární klíč je nejmenší podmnožina sloupců dané tabulky jednoznačně určující hodnoty všech sloupců. Pomocí znalosti hodnot sloupců tvořících primární klíč dokážeme získat i zbývající hodnoty. Místo nejmenší podmnožiny se však často do tabulky vkládá tzv. umělý klíč. Otázkou je, jakým datovým typem by měl být umělý klíč reprezentován. V rámci primitivních datových typů jazyka C# jsou nejvhodnější kandidáti int a Guid. Oba tyto typy lze mapovat na datové typy poskytované MSSQL databází. Pro použití intu hovoří fakt, že je méně paměťově náročný. Dále je int vhodný z toho důvodu, že MSSQL umožňuje nastavení sloupce obsahující hodnoty typu int jako tzv. identitu. V tom případě jsou hodnoty pro tento sloupec automaticky generovány, což zajišťuje požadovanou unikátnost hodnot v daném sloupci. Dalším plusem oproti Guid je rychlejší provedení SQL operace JOIN založené na 21

porovnání sloupců typu int, než typu uniqueidentifier, což je typ odpovídající C# typu Guid. Použití datového typu Guid je vhodné v případě, kdy nechceme umožnit procházení záznamu pomocí tipování hodnoty primárního klíče. Proměnná typu Guid obsahuje jednu hodnotu z intervalu 0-2 48 a tak je velmi nepravděpodobné, že kdokoliv najde v rozumném čase hodnotu, která je hodnotou primárního klíče záznamu v naší databázi. 3.5.2 Nastavení cizích klíčů a relací Pro udržení dat v konzistentním stavu se v databázích používají relace mezi entitami. Pomocí relací lze nastavit akce, které se mají provádět v případě, že je odkazovaný objekt modifikován nebo mazán. Relace jsou definovány prostřednictvím cizích klíčů. Entity Framework obsahuje implicitní jmenné konvence, na jejichž základě jsou relace nastavovány. Pokud nám relace nastavené pomocí implicitních jmenných konvencí nevyhovují, můžeme je explicitně nastavit pomocí atributů a Fluent API. Fluent Api je prostředek pomocí nějž můžeme definovat vazby, relace mezi doménovými typy. Tyto vazby se definují v metodě OnModelCreating třídy poděděné od třídy DbContextu. Definice relace 1:N, která například odpovídá zařazení prvků do skupin, s explicitním uvedením cizího klíče je vidět na obrázku 7. Součástí znázorněného kódu je i zakázání kaskádového mazání. Díky zakázání kaskádového mazání by v uvedeném příkladě nešlo smazat skupinu, která obsahuje alespoň jeden prvek. Obrázek 7: Definice relace 1:N pomocí Fluent Api Způsob změny jmenných konvencí pro určení cizího klíče pomocí atributu je vhodný v případě, že cizí klíč je tvořen jedinou proměnou. Této situaci odpovídá použití umělých primárních klíčů. Pokud je primární, cizí klíč definován přes více proměnných, například v mezitabulce potřebné pro vazbu M:N, je potřeba určit pořadí dílčích proměnných v klíči. Tehdy je jednoduší použít definici cizího klíče skrz Fluent Api. N+1 problém Entity Framework poskytuje funkčnost zvanou navigační proměnné. Pomocí nich můžeme z entity obsažené v relaci získat i data entit, která s ní jsou v relaci. Tím odpadá nutnost explicitního spojování potřebných tabulek pomocí příkazu JOIN. 22

Potencionální problém s použitím navigačních proměnných spočívá v tom, že data referencované entity jsou implicitně získávána až v okamžiku, kdy jsou opravdu potřeba. Což je technika zvaná Lazy Loading. V případě, že tato data potřebujeme získat pro každou entitu původní kolekce velikosti N, je potřeba do databáze provést dalších N dotazů na jejich získání. Přičemž dotaz do databáze je drahá operace. Proto o dříve zmíněném problému mluvíme jako o N+1 problému. Způsob, jak se tomuto problému vyhnout uvádí Gil Fink [28]. Řešení je jednoduché, stačí Entity Frameworku explicitně říci, pomocí příkazu Include, aby hodnoty všech navigačních proměnných získal v rámci jednoho dotazu do databáze. 3.5.3 Dědičnost O různé reprezentaci dat v databázi a aplikaci jsme se bavili již v kapitole 3.2. Tento problém se týká i dědičnosti, kdy v databázích máme více způsobů reprezentace dědičnosti. Obrázek 8: Dědičnost v aplikaci a způsob její reprezentace v databázi Při užití Entity Frameworku existují tři způsoby, jak dědičnost reprezentovat na straně databáze. Ty jsou popsány například na blogu asp.net [29]. 1. Při použití Table Per Hierarchy existuje jediná tabulka obsahující data všech poděděných typů. O typu dané instance se rozhoduje na základě hodnoty určitých sloupců. Sloupce, které nejsou v daném poděděném typu obsaženy, jsou nastaveny na null. 2. Jsou-li v databázi tabulky reprezentující pouze konkrétní typy, mluvíme o způsobu zvaném Table Per Concrete Type. Pomocí této reprezentace můžeme mít v databázi velké množství redundantních dat. To v případě, že máme několik potomků jednoho předka. Tehdy každý z potomků obsahuje hodnoty společných proměnných. S tím souvisí i problémy spojené s aktualizací společných proměnných, neboť ty se musí propagovat do všech potomků. 23

3. Poslední způsob je Table per Type. V tomto případě databáze obsahuje tabulku pro každý typ. Přičemž dědičnost je řešená pomocí relací, tak je vidět na obrázku 8. Každá instance má tak dostupná i data definovaná ve svém předku. Zároveň nejsou data společného předka uložena v databázi víckrát. Tyto vlastnosti tak zajišťují optimální využití databáze. Výběr V aplikaci byl použit přístup TPT, který uchovává data v neredundantní formě a netrpí problémy s aktualizací vícenásobně uložených hodnot. 3.5.4 Automaticky generované klíče a transakce Při použití Entity Frameworku se provádějí změny v tzv. Unit Of Work, což je kolekce dat s kterými v rámci probíhajícího dotazu pracujeme. Změny provedené pomocí volání metod třídy DbSet, což je třída jmenného prostoru System.Data.Entity, se nepropagují rovnou do databáze, ale ukládají se pouze lokálně. K tomu, aby se provedené změny uložily do databáze, je nutné explicitně zavolat virtuální metodu SaveChanges třídy poděděné od DbContext. Volání této metody v sobě zahrnuje transakční zpracování. Toto transakční zpracování není dostačující v případě, že potřebujeme během dávkového zpracování postupně získávat hodnoty automaticky generovaných klíčů. Obrázek 9: Získávání automaticky generovaných hodnot v rámci transakčního zpracování Hodnoty automaticky generovaných klíčů jsou do atributů dosazeny až při volání metody SaveChanges. Pokud tedy chceme pracovat s hodnotami klíčů, například na jejich základě pojmenovávat uploadované soubory, a přitom 24

zachovat transakční zpracování, tak musíme celý funkční blok obalit standardní transakcí. Příklad takového zpracování je vidět na obrázku 9, kde je znázorněn kód metody transakčně ukládající soubory pod jménem obsahujícím primární klíč daného záznamu. 25

4 Analýza použitých konceptů a technik V kapitolách 2 a 3 jsme si vybrali základní prostředky pro tvorbu webové aplikace. Zbývá nám dořešit například otázky týkající se provázání jednotlivých částí aplikace, rozšiřitelnosti a bezpečnosti. 4.1 Oddělení závislostí Webová aplikace napsaná pomocí návrhového vzoru MVC [4] je rozdělena do tří nezávislých částí, tak jak bylo popsáno v kapitole 2.2.1, což je v souladu s principem oddělením závislostí, což bylo řečeno na začátku kapitoly 2.4. Aby mohla jedna část využívat služby části druhé, tak na ní musí mít referenci. O objektu využívajícím služby mluvíme jako o konzumentu a referencovaný objekt nazýváme komponentou. V naší aplikaci například musí obsahovat controller referenci na model, tak aby mohl manipulovat s obsahem aplikace. Controller je tedy konzument a model představuje komponentu. Builder 2. Vložení závislostí 1. Vytvoření Client Service IService 3. Používání Obrázek 10: Proces využívání služeb při vkládání závislostí Problém spojený s použitím konzumenta a komponent spočívá v inicializaci komponent, kterou může provádět sám konzument, nebo může být provedena jinou částí aplikace a konzumentu předána, tak jak je vidět na obrázku 10. Na něm třída Client využívá služby vloženého objektu implementujícího rozhraní IService. Základními způsoby, jak provést vkládání závislostí jsou: 1. Způsob, kdy si konzument sám inicializuje ostatní komponenty, se označuje jako těsná vazba. Její použití není příliš vhodným řešením. Především z toho důvodu, že pokud chceme, aby konzument pracoval s jinou implementací komponenty, musíme měnit i jeho kód. Dále proto, že se konzument musí sám starat o životní cyklus použitých komponent. 2. Poor man s dependency injection je dalším způsobem, jak můžeme řešit závislosti konzumenta na komponentách. Pro jeho vysvětlení budeme uvažovat situaci, kdy konzument používá pouze jednu komponentu. Tehdy si vystačíme s definicí dvou konstruktorů. Kde jeden z nich je bezparametrický a při jeho zavolání se automaticky volá jeho přetížení, kterému jako parametr předává defaultní implementaci komponenty. To nám přináší možnost předání jiné implementace komponenty pomocí parametrického konstruktoru. 26

3. Nejvhodnějším řešením je použití vkládání závislostí (dále jen DI, což je zkratka z anglických slov Dependency Injection) [17]. Tehdy je konzument zcela odstíněn od inicializace komponent, které používá. Ty jsou inicializovány pomocí tzv. dependecy injectoru a konzumentu předány v případě, že si o ně požádá. Díky tomu není konzument omezen na použití jedné implementace komponenty. Naopak konzumentu mohou být předány i takové implementace komponenty, které mu nejsou v době překladu známy. V rámci inicializace komponent pomocí dependency injectoru jsou řešeny i závislostní řetězy, tedy závislosti obsažené v komponentách atd. Jelikož chceme, aby aplikace dodržovala doporučené postupy v programování, tak je v ní použito vkládání závislostí. 4.1.1 Způsoby vkládání závislostí Existuje více způsobů vkládání závislostí, které se liší v tom, kdy k vložení dochází. Způsoby vkládání závislostí lze rozdělit do dvou skupin: 1. Vkládání v rámci volání konstruktoru se v literatuře označuje jako constructor injection. Má tu výhodu, že konzument má komponentu k dispozici po celou dobu svého životního cyklu a nikdo mu během jeho života nemůže předa jinou implementaci, čímž by se mohla porušit konzistence provádění. To, že má konzument k dispozici komponentu po celou dobu svého života je problém v případě, má-li komponenta velké paměťové, či jiné nároky. Protože pak je například paměť potřebná pro komponentu alokovaná po celou dobu života konzumenta, i když není komponenta používána, což jistě není vhodné chování. 2. Dalšími způsoby jsou vkládání pomocí rozhraní, setteru a vlastností třídy. Ty mají tu výhodu, že komponenta je inicializována až v případě, kdy jí konzument opravdu potřebuje. Nevýhodou tohoto přístupu je nutnost testování již proběhnuté inicializace komponenty a možnost předání jiné implementace během života konzumenta, což může vést k neočekávaným a tedy i špatným výsledkům. Na internetu je dostupná řada dependecy injectorů pro.net. Jedním z nich je i open-sourcový projekt Ninject [www.ninject.org]. Jeho funkčnost neobsahuje pouze vkládání na základě definovaných vazeb, ale i pokročilé techniky jako vkládání na základě jmenných konvencí, správu životního cyklu komponent a možnost načítání nových modulů. Dalším významným dependency injectorem je MEF [http://mef.codeplex.com/] (což je zkratka anglických slov Managed Extensibility Framework), jenž je vyvíjen Microsoftem. Funkčnost, kterou obsahuje MEF, však neobsahuje například tak pokročilou správu životního cyklu komponent, jako je v to v případě Ninjectu. Výběr vhodného depency injectoru je uveden v příští kapitole, jelikož jeho výběr v našem případě závisí i na funkčnosti, kterou se příští kapitola zabývá. 27

4.2 Rozšiřitelnost Jedním z námi stanovených cílů je rozšiřitelnost výsledné aplikace. Té jde dosáhnout i pomocí modifikace zdrojových kódů původní aplikace. Toto řešení však není vhodné především při nasazení nové funkcionality do více instancí aplikace najednou. Například v případě, že máme více verzí naší aplikace, které se liší v poskytované funkcionalitě, a do všech chceme přidat funkcionalitu novou, případně změnit funkcionalitu přítomnou ve více verzích. Pak je potřeba upravit zdrojový kód všech verzí aplikace, což je řešení náročné na čas a náchylné na chyby. Vhodnějším způsobem je vytvoření modulární aplikace, která bude umožňovat přidávání nových a změnu existujících modulů bez nutnosti zásahu do zdrojového kódu hlavního modulu. Hlavním modulem je myšlena ta část aplikace, která má na starosti načítání ostatních modulů. V případě změny poskytované funkcionality poté stačí hlavnímu modulu předat implementaci nového modulu, případně novou implementaci modulu již existujícího. Přidávání nových modulů by mělo být založené na mechanismu, který si sám najde všechny dostupné moduly a zaregistruje si je tak, aby mohl využívat funkčnost jimi poskytovanou. Zmíněný mechanismus by mohl fungovat například na principu jmenných konvencí, tak jako na obrázku 11, kde hlavní modul načítá všechny moduly, které jsou uložené v definovaném adresáři a jmenují se Plugin*. Díky tomu by mohl libovolný programátor přidat nový modul v případě dodržení definovaných jmenných konvencí. MainModule Plugin1 AnotherApp Plugin2 Adresář s přídavnými moduly Obrázek 11: Načítání modulů na základě jmenných konvencí Přidávání nové funkcionality na základě jmenných konvencí je použito ve výsledné aplikace. V prostředí.net lze přidávání na základně jmenných konvencí dosáhnout například pomocí Reflection, frameworku MEF a projektu Ninject. 4.2.1 Reflection Reflection je součást.net frameworku poskytující funkčnost potřebnou ke zkoumání a modifikaci objektů za běhu programu. Dále umožňuje projektu načíst moduly, které mu nejsou známy v době překladu. Což je přesně to, co potřebujeme udělat v případě, že chceme do stávající aplikace přidat novou funkcionalitu. Detailní návod k načítání modulů uvádí na svém na blogu Long Lee [30]. Nevýhodou tohoto řešení je absence mechanismů zajišťující DI [17]. Tím pádem bychom museli kromě Reflection použít ještě jiný nástroj pro vkládání závislostí. 28

4.2.2 MEF MEF obsahuje kromě funkčnosti zajišťující DI i funkčnost zjednodušující vytváření rozšířitelných aplikací. MEF funguje na principu kontraktů. Ty nám definují, objekt jakého typu je potřeba do dané instance dosadit, případně objekt jakého typu může daný objekt poskytnout. Proto nám pro dosazení konkrétní implementace daného typu stačí objekt opatřit atributem Import s typem, jehož instanci chceme dosadit. Přičemž MEF se pokusí najít objekt opatřený atributem Export se stejným typem a dosadit ho. Na blogu Scotta Hanselmanna [31] jsou dostupné detailní informace o použití MEF v rámci zprovoznění modularity u webových aplikací. 4.2.3 Ninject O Ninject jsme se už zmínili v rámci kapitoly 4.1.1. Jedno z rozšíření tohoto projektu, konkrétně Ninject.Extensions.Conventions, umožňuje načítání modulů odpovídajících definované jmenné konvenci před spuštěním aplikace. Mají-li být přídavné moduly navrhnuty v principu oddělení závislostí, je potřeba definovat k tomu potřebné vazby. Aby každý z modulů nemusel obsahovat vlastní instanci dependency injectoru umožňuje Ninject registrování vazeb v dependency injectoru hlavního modulu. Nejjednodušším způsobem, jak registrování vazeb docílit, je do modulu přidat třídu poděděnou od třídy NinjectModule. Virtuální metoda Load této třídy je Ninjectem volána v okamžiku, kdy je daný modul načten hlavním modulem. Více informací můžeme opět dostat na blogu Longa Leeho [30]. 4.2.4 Volba V aplikaci potřebujeme vkládat závislosti a načítat moduly. U vkládání závislostí chceme určovat, jakou instanci vkládané třídy chceme vkládat. Všechny zmíněné problémy jsou řešitelné pomocí Ninjectu, který obsahuje jak mechanismus vkládání na základě jmenných konvencí, tak i správu životního cyklu vkládaných objektů. Díky tomu, že Ninject obsahuje všechny požadované mechanismy je použit ve výsledné aplikaci. 4.3 Zabezpečení V kapitole 2.4.3 bylo řeč o tom, že v ASP.NET MVC lze zpřístupnit funkcionalitu metod, či celých tříd, jen vybraným uživatelům a to pomocí atributu Authorize. Funkčnost tohoto atributu bude popsána v kapitole 4.3.1. Kromě ochrany naší aplikace v podobě omezení přístupu chceme také zabránit útokům ze strany hackerů. Mezi jejich nejpoužívanější techniky útoku na webové aplikace patří Cross-site scripting, Cross-site request Forgery a SQL injection. Zabezpečením aplikace napsané pomocí ASP.NET MVC proti těmto útokům se budou zabývat kapitoly 4.3.3-4.3.5. 29

4.3.1 Autorizace a autentizace Autorizace se často zaměňuje s autentizací, což je proces ověřování identity určitého subjektu. Autorizace si můžeme představit jako získání souhlasu, což často navazuje na autentizaci. Jako příklad, kdy autorizace nesouvisí s autentizací, může posloužit omezení přístupu k dané třídě, metodě v závislosti na aktuálním čase. Což je běžné například u dávkových operací, které hodně zatěžují server, a tak není vhodné jejich spouštění během dne. V případě, že autorizace navazuje na autentizaci je třeba funkčnosti ověřující identitu uživatele. V ASP.NET jsou implicitně přítomny dva přístupy k autentizaci. 1. Windows Authentification. Tento přístup je vhodný spíše pro intranetové aplikace. Autentizace pomocí Windows Authentification probíhá vůči uživatelským účtům, jež jsou definovány na hostitelském serveru. Díky tomu se nemusíme starat o uživatelské účty, jelikož ty jsou převzaty od operačního systému. Kvůli vazbě na uživatelské operačního systému je toto řešení málo pružné a tedy i nevhodné pro použití ve webové aplikaci veřejného charakteru. U aplikace veřejného charakteru můžeme chtít umožnit oprávněný přístup i uživateli, který nemá uživatelský účet na hostitelském serveru. 2. Forms Authentification. V tomto případě jsou uživatelské účty v rámci aplikace nezávislé na těch použitých operačním systémem. Za zdánlivou nevýhodu bychom mohli považovat fakt, že cílová aplikace musí obsahovat funkcionalitu na správu uživatelů a jejich rolí. ASP.NET MVC však poskytuje defaultní implementace tříd obsahujících tuto funkcionalitu. Rámcově jsou tyto třídy nazývány providery. V případě, že nám nevyhovuje způsob, jakým providery fungují, reprezentují data, je možné defaultní implementace nahradit vlastními. 4.3.2 Providery ASP.NET obsahuje defaultní implementace Membership, Role, Profile a Session providerů. Pomocí těchto providerů můžeme spravovat oprávněné uživatele, jejich role, rozšiřující informace o oprávněných uživatelích a také Session. Session je mechanismus pro uchovávání stavu aplikace v rámci komunikace s uživatelem. V rámci výsledné aplikace chceme mít u záznamů různých typů dat obsažené i informace o autorovi. Pokud informacemi nemyslíme pouze uživatelské jméno daného uživatele, ale například křestní jméno a příjmení, musíme k jejich získání použít nejen metody Membership provideru ale i Profile provideru. Profily, které drží dodatečné informace, jednotlivých uživatelů jsou v případě použití defaultního provideru ukládána v nevhodné formě. To z toho důvodu, že v použité tabulce je u každého záznamu zároveň uložená i jeho struktura, což činí uložená data redundantní. Použití metod obou providerů a nevhodná struktura ukládaných dat, jsou hlavní důvodu k tomu, že v cílové aplikaci jsou defaultní implementace nehrazeny vlastními implementacemi. 30

4.3.2.1 Uživatelé a jejich role Defaultní implementace role provideru umožňuje přiřazení uživatele do více uživatelských rolí. To je ale málo pružné řešení, jelikož omezení u metod a tříd je zapsané v kódu aplikace a tak není možné vytvořit nové role, které by zjemňovaly nastavení přístupu k jednotlivým metodám. M N User Role Permission M N M N Package Obrázek 12: Schéma tabulek udržujících informace o uživateli a jeho oprávněních Zjemnění nastavení jsme v aplikaci dosáhli pomocí zavedení další vrstvy, tak jak je znázorněné na obrázku 12. Uživatel může být dále přiřazen do více rolí. Každá z rolí obsahuje seznam oprávnění ke všem dostupným balíčkům. Balíčky obsahují funkcionalitu spojenou s určitým datovým typem, kterým jsou například aktuality, události v kalendáři, fotogalerie a videogalerie. Díky zavedení oprávnění k jednotlivým balíčkům nejsou v rámci atributů Authorize uváděny pouze názvy rolí, ale i názvy balíčků, k nimž jsou požadovaná oprávnění. Uživatel má oprávnění k danému balíčku tehdy, má-li ho alespoň jedna z rolí, která je mu přiřazena. Součástí třídy Permission, viz obrázek 12, reprezentující oprávnění role k danému balíčku není pouze údaj určující, jestli má uživatel v dané roli přístup k vybranému balíčku, ale také rozšiřující údaj, který určuje, jestli uživatel v dané roli může spravovat všechny záznamy datového typu, pro nějž je daný balíček definován. Uživatel může spravovat jen záznamy jím vytvořené, pokud žádná z jemu přiřazených rolí nemá úplné oprávnění k danému balíčku. 4.3.3 Cross-site scripting Mezi nejrozšířenější prohřešky proti bezpečnosti webových aplikací patří možnost vkládání HTML kódu do našich stránek. To umožňuje hackerům vložit takový kód, který se provede při každé návštěvě dané stránky. Takový to způsob útoku se označuje jako cross-site scripting. ASP.NET obsahuje dvě jednoduchá řešení, jak aplikaci ochránit proti útoku vedeného formou cross-site scripting: 1. Validace přijatých dat. Defaultně tato data nesmí obsahovat znaky, které mají v HTML speciální význam. Díky tomu není možné, aby hacker vložil do našich stránek škodlivý kód. 2. Další způsob obrany není založen na validaci přijatých dat, ale na jejich dekódování při vypsání do stránky. Díky tomu je zrušen speciální význam škodlivých znaků. Nebezpečný kód se tak místo provedení pouze vykreslí do stránky. 31

4.3.4 Cross-site request Forgery Cross-site request Forgery je útok fungující na bázi nechtěného dotazu do aplikace. Pokud hacker odhalí strukturu napadané aplikace, může pomocí podstrkávání dotazů oprávněným uživatelům provádět akce, které mu nejsou jinak přístupné. ASP.NET MVC přichází s mechanismem založeném na shodě přijatého a uloženého tokenu v rámci zpracování kritických akcí. Přičemž hodnota tokenu je jedinečná pro každé přihlášení uživatele. Případný hacker tak nemá možnost aktuální hodnotu tokenu získat. Díky tomu podstrčený dotaz neobsahuje aktuální hodnotu tokenu a požadovaná akce se neprovede. 4.3.5 SQL injection V souvislosti s SQL injection mluvíme o útoku na databázovou vrstvu aplikace. S tou mohou hackeři komunikovat díky nedostatečné kontrole vstupních dat, která aplikace používá jako parametry SQL skriptů. Pro zabránění zmíněné komunikaci stačí použít parametrizované dotazy. Ty své parametry automaticky escapují, čímž ruší význam všech nebezpečných znaků. Parametrizované dotazy jsou využívány i ORM nástroji. Použití ORM nástroje tedy pouze nezjednodušuje práci s databází, ale i zvyšuje zabezpečení celé aplikace. 4.4 Práce s výjimkami Za běhu aplikací může docházet k chybovým situacím. O těch nás jazyk C# informuje pomocí výjimek. Vyhozená výjimka však neobsahuje pouze příslušnou chybovou hlášku ale i informace o volání, hodnotách parametrů atd. To všechno jsou implementační detaily, které nechceme zveřejňovat uživatelům naší aplikace. Aby při vyhození výjimky nedocházelo k zobrazení implementačních detailů, obsahuje jazyk C# konstrukci try-catch. Pomocí ní je možné vyhozené výjimky zachytit a případně zpracovat. Rozhodně špatným přístupem by bylo výjimky pouze zachytávat, ale již neprovádět žádné další akce související s jejich zachycením. Tehdy by byl uživatel aplikace nejspíše dost zoufalý, že aplikace funguje, jak má, ale jemu se přesto nedaří provést požadované úkony. O trochu lepším řešením by bylo přidání zobrazení omluvné hlášky uživateli. V tom případě by uživatel již nemusel být zoufalý, ale my bychom stále neměli ani ponětí o tom, že k nějaké chybové situaci došlo. Nejvíce používané řešení obsahuje zachycení výjimky, zaregistrování informací v ní obsažených a zobrazení omluvné hlášky uživateli. Jelikož je toto řešení nejčastěji používané, můžeme ho zároveň považovat i za nejlepší možné. 4.4.1 Logování výjimek Z důvodu časté implementace posledního řešení existují na internetu knihovny na zpracovávání vyhozených výjimek. Jednou z nich je i knihovna Elmah dostupná na adrese https://code.google.com/p/elmah/. Pomocí ní lze odchytit všechny dříve neodchycené výjimky, zapsat jejich informace do 32

persistentního úložiště a přesměrovat uživatele na stránku s omluvnou hláškou. Stačí si uvědomit, že takové řešení jsme si v minulém odstavci uvedli jako ideální. Způsob, jakým má tato knihovna v rámci aplikace fungovat, lze do velké míry měnit pomocí nastavení uvedeného v konfiguračním souboru a kódu aplikace. Mezi nejzákladnější nastavení patří výběr persistentního úložiště, do kterého se mají informace o výjimkách ukládat. S ukládáním informací souvisí filtrování výjimek. Díky filtrování můžeme ignorovat výjimky typu přístup na neexistující stránku a chybějícího obrázku. Elma dále umožňuje automatické zasílání e-mailu v případě nově zachycené výjimky. Více o nastavení knihovny se lze dočíst na dříve uvedené adrese. 4.5 Testování Kontrola požadované funkčnosti aplikace je komplexní úlohou. V případě manuální kontroly se jedná i o časově náročnou úlohu. Z toho důvodu se při vývoji aplikací používají testy, které lze nadefinovat a poté opakovaně spouštět. Použití návrhového vzoru MVC, kde každá část aplikace je zaměřená na konkrétní úkol, činí aplikaci lépe testovatelnou. To právě díky přesně definované funkčnosti daných částí. Testování aplikace usnadňuje i použití Visual Studia, v němž jsou integrovány nástroje, jako je framework Unit Testing, podporující dávkové testování. V oblasti vývoje webových aplikací se používají především dva druhy testování a to Unit testy a Integration testy. 4.5.1 Unit a integration testy Unit testy [17] jsou technikou testování jednotlivých aspektů třídy, případně metody. Opačný přístup, kdy se testuje kompletní výsledek volání aplikace, se označuje jako integration testy. V oblasti vývoje webových aplikací se používají spíše unit testy. Ty se jednodušeji píší a při změně testovaného kódu nás ihned informují o tom zda, případně kde a jak jsme změnily požadovanou funkčnost. Což je výhoda oproti výsledku poskytnutému integration testy, který nás pouze informuje o tom, že při zpracování celého volání proběhlo něco špatně. Integration testy se používají spíše v případě, kdy chceme odhalit chyby v již existujících implementacích. S použitím unit testů se mění i styl vývoje aplikace. Ten se nazývá programování řízené testy nebo anglicky Test-driven development dále jen TDD [17] a byl použit při vývoji výsledné aplikace. 4.5.2 Programování řízené testy Princip vývoje aplikace pomocí TDD je založen na vývojovém cyklu zvaném Red-green refactor. Tento cyklus obsahuje následující body, přičemž výsledky spouštěných testů jsou reprezentovány pomocí různých barev kontrolek. 33

1. upřesnění požadovaných výsledků volání třídy, metody a napsání testů, které tyto výsledky zkontrolují 2. spuštění testů a zkontrolování, že všechny kontrolky mají červenou barvu 3. napsání kódu testované třídy, metody 4. spouštění testů a modifikace testovaného kódu, dokud nebudou všechny kontrolky zelené 5. refactoring testovaného kódu 6. kontrolní spuštění testů K napsání unit testů pro danou metodu, třídu potřebujeme nejdřív přesně pochopit jakou funkčnost má tento funkční blok obsahovat. Díky tomu jsme schopni lépe výslednou metodu, třídu navrhnout, protože přesně chápeme požadavky na ní kladené. V případě, že aplikace obsahuje těsné vazby, jsou výsledky unit testů závislé i na funkčnosti použitých komponent. Tento problém je ale eliminován v momentě, kdy naše aplikace používá mechanismus vkládání závislostí. 4.5.3 Vkládání závislostí Díky DI [17] můžeme předložit testované třídě, metodě jen falešnou implementaci (někdy se můžeme setkat s pojmem Mock nebo Stub) používané komponenty. To činí unit testy nezávislé na použitých komponentách, s čímž souvisí i jejich rychlejší provádění. Unit testy tak nefungují například nad reálnou databází, ale pouze nad kolekcí dat požadovaného typu. Falešnou implementací komponenty z předchozího odstavce je myšlen takový objekt, který definuje pouze funkčnost potřebnou pro běh testované jednotky. Pro vytváření takových implementací je na internetu dostupná řada knihoven. Pomocí těch lze vytvořit falešnou implementaci jakéhokoliv rozhraní s minimálním vynaloženým úsilím. Jednou z takových knihoven je i knihovna Moq, která je dostupná na adrese code.google.com/p/moq/. Výhoda knihovny Moq spočívá v její jednoduchosti. Tato knihovna je použita pro vytváření falešných implementací i v ukázkách uvedených v dostupné literatuře. Obrázek 13: Implementace falešné funkcionality pomocí lambda funkce Moq nám umožňuje pomocí lambda funkcí definovat falešnou funkcionalitu pro téměř libovolnou metodu viz obrázek 13, kde vytváříme falešnou implementaci atributu typu IQueryable<Item>. Mezi metody, pro které nejde v současné době pomocí frameworku Moq vytvořit falešnou implementaci, patří ty, které mají alespoň jeden z parametrů opatřen klíčovým slovem ref či out. 34

4.5.4 Spouštění testů K automatickému testování aplikace je potřeba použít nástroj, framework umožňující dávkové spouštění definovaných testů. V aplikaci je k testování použit framework Unit Testing, který je součástí Visual Studia, a obsahuje veškerou potřebnou funkcionalitu. Unit Testing framework Tento framework používá k identifikaci testů atributy, tak jak je vidět na obrázku 14, kde je definovaný jeden test, který vždy skončí kladným výsledkem. Při dávkovém testování jsou spuštěny všechny metody, které jsou opatřeny atributem TestMethod, v třídách opatřených atributem TestClass. Kromě atributů určujících testovací metody obsahuje framework i atributy definující podpůrné metody. Mezi tyto atributy patří TestInitialize a TestCleanUp. V metodě opatřené atributem TestInitialize bývá z pravidla obsažen kód, který nainicializuje data potřebná pro běh testů. Tato metoda je volána před spuštěním libovolného testu dané třídy. TestCleanUp naopak definuje metodu, která se spouští po doběhnutí jednotlivých testů a která má na starosti případné disposování použitých objektů. Obrázek 14: Třída definující jeden Unit Test Kromě atributů definujících význam jednotlivých funkcí framework obsahuje i atribut, jehož použitím říkáme, že jako výsledek testu očekáváme výjimku. Díky tomu nemusíme kód testu uzavírat do try-catch bloku. Testování funkčnosti je založeno na porovnávání návratových hodnot. Těmi mohou být primitivní, komplexní typy a vyhozené výjimky. V případě komplexních typů jde především o porovnání hodnot obsažených atributů. JSONResult V případě použití návratového typu JSONResult C# v době překladu neví, jaký typ dat bude zabalen do objektu typu JSON, jenž je výsledkem volání. Kvůli tomu nemůžeme přistupovat k atributům objektu, jenž je obsažen v objektu JSON. Proto musíme k porovnání návratové hodnoty použít Reflection. Reflection nám poskytuje funkcionalitu, pomocí níž můžeme na objekt hledět jako na instanci zvoleného typu a zkontrolovat hodnotu požadovaného atributu, tak jak je vidět na obrázku 15, kde používáme Reflection k otestování hodnoty atributu property třídy zabalené do typu JSON. 35

Obrázek 15: Testování návratové hodnoty pomocí Reflection 4.6 Design aplikace Pro splnění požadavků stanovených v kapitole 1.2.2 je potřeba rozsáhlá funkcionalita. Proto je vhodné, aby výsledná aplikace byla rozdělena do více modulů, což je možné díky rozhodnutí z kapitoly 4.2, kde jsme se rozhodli, že výsledná aplikace bude modulární. Aplikace, která je znázorněna na obrázku 16, je tvořena hlavním modulem (BaseModule), který bude registrovat ostatní moduly. Těmi jsou DocumentPlugin, který obsahuje například správu aktualit, událostí, zaměstnanců, jejich rolí a dále funkcionalitu potřebnou pro správu úložiště vzdělávacích materiálů. MediaPlugin obsahující správu fotogalerií a videogalerií. BaseModule DocumentPlugin MediaPlugin Obrázek 16: Rozdělení aplikace do modulů Díky rozdělení aplikace do modulů můžeme poskytovat různé verze aplikace v závislosti na obsažené funkčnosti, případně dílčí moduly používat v rámci jiných aplikací. Tím splníme je jeden z bodů uvedených v kapitole 1.3, která obsahovala motivaci k vývoji nového CMS. V kapitole 2.4.2 jsme uvedli, že by model neměl obsahovat žádnou vazbu na zbylé části aplikace. Díky tomu je možné oddělení modelu do samostatného projektu, tak aby byla zajištěna nezávislost modelu na ostatních částech aplikace. Tento projekt se v aplikaci jmenuje Domain. V kapitole 4.5 jsme rozhodli, že při vývoji aplikace budeme postupovat podle principu TDD [17]. Jelikož pro běh výsledné aplikace, není kód unit testů potřeba, je vhodné, aby i definice Unit Testů tvořily samostatný projekt. Ten se v aplikaci jmenuje UnitTest. Díky oddělení Modelu a Unit Testů do samostatných projektů se aplikace rozpadne do tří projektů mezi kterými existují následující vazby: Projekt Web obsahuje vazbu na projekt Domain, který obsahuje business logiku a také poskytuje funkcionalitu pro komunikaci s databází. Projekt UnitTest obsahuje vazby na zbylé dva projekty, tak aby mohl testovat funkcionalitou v těchto projektech definovanou. 36

Domain Web UnitTest Obrázek 17: Struktura každého modulu aplikace Na předchozím obrázku je znázorněné rozdělení modulu do projektu spolu se zobrazením vazeb jednotlivých projektů na projekty ostatní. Vazby jsou reprezentovány pomocí šipek. Například projekt Web má vazbu na projekt Domain. Rozdělení modulu do 3 projektů je provedeno u všech modulů ve výsledné aplikaci. 37

5 Vývojová dokumentace V kapitole 4.6 jsme se rozhodli pro rozdělení aplikace do 3 modulů. Toto rozdělení bylo vidět na obrázku 13. Každý z modulů je tvořen více projekty. Ty jsou ve Visual Studiu reprezentovány soubory typu.csproj. Projekty jsou kompilovány do dynamicky linkovaných knihoven, což jsou soubory typu dll. Každý z projektů je uložen v samostatném adresáři a definuje jmenný prostor stejného názvu jako je název projektu. Struktura a princip fungování aplikace budou rozebrány v kapitolách 5.1-5.3. V kapitole 5.4 budou popsány frameworky a vysvětlena řešení použitá v rámci všech modulů aplikace. Kapitoly 5.5-5.7 budou obsahovat popis jednotlivých modulů. 5.1 Základní struktura zdrojových kódů Projekty jednotlivých modulů mají názvy *Domain, *Web(Plugin), *UnitTest, kde hvězdička představuje název vybraného modulu. Tato konvence bude použita i ve zbytku této kapitoly. U projektu Web je uvedeno (Plugin) z toho důvodu, že v případě přídavných modulů se tento projekt nejmenuje například DocumentWeb, ale DocumentWebPlugin. Projekty reprezentující části jednotlivých modulů obsahují vždy stejnou základní strukturu. Ta je určena jmennými prostory, které jsou definovány v daném projektu. U projektů *Domain, reprezentují model jednotlivých modulů, to jsou následující jmenné prostory: *Domain.Entity obsahují definice doménových typů daného modulu *Domain.Abstract obsahují definice rozhraní, pomocí nichž se manipuluje v databázi s doménovými typy daného modulu *Domain.Concrete obsahují konkrétní implementace rozhraní z jmenných prostorů *Domain.Abstract a implementace tříd poděděných od DbContext, které jsou v modulech použity ke komunikaci s databází Projekty *Web, které obsahují definice controllerů a pohledy daných modulů, obsahují jmenné prostory: *Web(Plugin) obsahují definice směrovacích pravidel vybraného modulu *Web(Plugin).Controllers obsahují definice controllerů, jež obsahují aplikační logiku modulů *Web(Plugin).Models obsahují definice modelů potřebných pro použití silně typových pohledů Pohledy daných modulů nejsou definovány v žádném jmenném prostoru. Projekty *UnitTest jsou tvořeny těmito jmennými prostory: *UnitTest.Controllers obsahují unit testy controllerů příslušného modulu *UnitTest.Routing obsahují testy, které testují funkčnost směrovacích pravidel daného modulu 38

Více budou třídy a rozhraní obsažené v jednotlivých jmenných prostorech probrány v kapitolách 5.5-5.7. 5.1.1 Struktura modulu BaseModule Projekt BaseModule je hlavním modulem výsledné aplikace. Z toho důvodu je v rámci tohoto modulu implementovaná i funkčnost potřebná k načítání a běhu přídavných modulů. Dále modul BaseModule obsahuje i naše implementace providerů. V projektu BaseDomain je kromě výše zmíněných jmenných prostorů obsažen i jmenný prostor BaseDomain.ValidationAttribute. Ten obsahuje kód námi vytvořených validačních atributů. Projekt BaseWeb obsahuje navíc jmenné prostory BaseWeb.Start_Up a BaseWeb.Providers. Jmenný prostor BaseWeb.Start_Up je tvořen třídami definujícími: vazby pro vkládání závislostí načítáni přídavných modulů jmenné konvence používané view enginem. Ve jmenném prostoru BaseWeb.Providers žijí naše implementace providerů. Projekt BaseUnitTest obsahuje navíc jmenné prostory odpovídající přidaným jmenným prostorům v projektech BaseDomain a BaseWeb. 5.1.2 Struktura modulů MediaPlugin a DocumentPlugin V rámci obou těchto modulů je třeba funkčnost, která provede nastavení vazeb daného modulu pro vkládání závislostí. Nastavení vazeb pro vkládání závislostí je obsaženo ve jmenném prostoru *WebPlugin.PluginStartUp. 5.2 Struktura výsledné aplikace V analýze jsme se rozhodli pro načítání přídavných modulů na základě jmenných konvencí. Z toho důvodu jsou v rámci výsledné aplikace všechny knihovny potřebné k běhu aplikace umístěny ve složce /bin, která je umístěná ve stejné složce jako konfigurační soubor web.config a soubor Global.asax. Soubor Global.asax reprezentuje vstupní bod aplikace napsané v ASP.NET MVC. Ostatní soubory modulu BaseModule tvoří strukturu typickou pro aplikaci napsanou pomocí ASP.NET MVC. Ta je určena následujícími složkami: /Content - obsahuje kaskádové styly a ostatní soubory tvořící design aplikace /Scripts obsahuje JavaScriptový kód aplikace, ten v našem případě obsahuje například implementaci textového editoru /Views obsahuje všechny pohledy používané v rámci projektu BaseWeb Kromě kódu přídavných modulů potřebujeme do aplikace přidat i jejich pohledy spolu s JavaScriptovými kódy a kaskádovými styly. Pohledy přídavných modulů jsou ve výsledné aplikaci umístěny ve složce Areas a dále zanořeny do složky, jejíž název koresponduje s názvem projektu 39

*WebPlugin daného modulu. Pohledy modulu DocumentPlugin jsou tak umístěny ve složkách vnořených do /Areas/MediaWebPlugin. Jako hlavní pohledy (anglicky Master view) jsou v celé aplikaci používané ty z hlavního modulu. Master view definují části, do kterých se má vkládat obsah z použitého pohledu tak, aby společné části stránky nebylo nutné definovat v každém pohledu samostatně. Obdobným způsobem je řešeno i umístění obsahu složek /Content resp. /Scripts přídavných modulů. Obsahy těchto složek jsou kopírovány do složek /Content/název resp. /Scripts/název, kde název zastupuje název projektu *WebPlugin. Spravované fotografie jsou uloženy ve složce /Photos a vzdělávací materiály jsou dostupné ve složce /Documents. Obě tyto složky musí mít přiřazené právo k zápisu. Složky Content, Documents, Photos a Scripts jsou součástí kořenového adresáře webu. 5.2.1 Databáze Jedním z požadavků na aplikaci je i vazba jednotlivých fotogalerií na jejich autory. Ve výsledné aplikaci je doménový typ reprezentující fotogalerie součástí jiného modulu než doménový typ reprezentující autora. Požadavek na vazbu na autora se týká i vzdělávacích materiálů. Z toho důvodu mají přídavné moduly referenci na hlavní modul. Díky této referenci používají přídavné moduly pro připojení k databázi připojení definované v hlavním modulu. Všechny moduly v aplikaci tedy fungují nad jednou databází. 5.2.2 Konfigurační soubor web.config Stejně jako v případě databáze je i konfigurační soubor sdílen všemi moduly. 5.3 Princip fungování aplikace Běh aplikace lze rozdělit do dvou fází: 1. Spuštění aplikace, které obsahuje načtení přídavných modulů a zaregistrování všech směrovacích pravidel. 2. Běh aplikace - zpracovávání požadavků Běh aplikace obsahuje několik kroků, ty lze zjednodušeně popsat pomocí následujícího obrázku. Požadavek 1 4 Odpověď Směrování Zpracování Vykreslení 2 3 Aktualizace dat Obrázek 18: Průběh zpracování požadavku 40

Směrování V tabulce směrovacích pravidel se najde první shoda. Získané údaje, kterými jsou jméno controlleru, jeho metody a další parametry, se pomocí několika, v tuto chvíli nepodstatných, kroků předají tzv. IControllerFactory. Bod 1 IControllerFactory se pokusí najít controller, což je třída implementující rozhraní IController, odpovídajícího jména ve všech dostupných assemblies. Díky načtení modulů při spuštění aplikace probíhá toto hledání i v přídavných modulech. V případě, že je odpovídající controller nalezen, se pokračuje ve zpracování, jinak je vrácena chyba controller was not found. Zpracování Je zavolána příslušná metoda controlleru. Pokud taková neexistuje, pak požadavek opět končí chybou, tentokrát action was not found. V rámci zpracování této metody může dojít k bodům 2 a 3 z obrázku 18, tedy ke komunikaci s modelem. V komunikaci dochází k aktualizaci, případně získání dat uložených v databázi, která je používána všemi moduly. Získaná data jsou nejčastěji předána do pohledu, kde mají být vykreslena. Bod 4 View engine se na základě definovaných jmenných konvencí pokusí najít odpovídající pohled. V případě, že požadovaný pohled není nalezen, tak požadavek končí chybou view was not found. Vykreslení V pohledu jsou vykreslená data přijatá od controlleru. 5.4 Společná řešení V následující kapitole se zaměříme na koncepty, knihovny a jazyky použité v rámci všech modulů tak, aby je nebylo třeba vysvětlovat u každého modulu zvlášť. 5.4.1 Databáze Všechny moduly spravují data uložená v databázi. Proto je potřeba se k této databázi připojit. V kapitole 3.3 jsme se rozhodli, že pro přístup k databázi budeme používat vrstvu datového přístupu. Ta je v našem případě reprezentována tzv. repositáři. 5.4.1.1 Připojení k databázi K připojení k databázi se v případě Entity Frameworku používá třída poděděná od třídy DbContext tak, jak je vidět na obrázku 19, kde jsou pomocí jediného atributu dostupné instance třídy Record uložené v databázi. Tato třída se při inicializaci automaticky připojí k databázi určené connection stringem, který jí předáme. V případě, že jí žádný nepředáme, se ho pokusí sama získat z konfiguračního souboru (web.config), kde hledá connection string se stejným názvem, jaký má sama. Každý repositář v aplikaci obsahuje referenci na třídu poděděnou od DbContext. 41

Obrázek 19: Definice třídy poděděné od DbContext spolu s atributem typu DbSet V třidě poděděné od DbContext se pomocí virtuální metody OnModelCreating mohou definovat relace mezi jednotlivými datovými typy. My jsme v kapitole 5.2.1 uvedli, že i v přídavných modulech chceme mít přítomny doménové typy, včetně jejich relací, spravované v hlavním modulu. Z toho důvodu se pro připojení k databázi v přídavných modulech nedědí přímo od třídy DbContext, ale od jejího potomka, který je implementován v hlavním modulu. Poté je možné v přídavných modulech volat metodu OnModelCreating implementovanou v hlavním modulu, což zajistí nastavení všech relací hlavního modulu. 5.4.1.2 Repositáře Rozhraní repositářů obsahuje 3 veřejné metody, a to Save, Delete a Commit a 1 atribut implementující rozhraní IQueryable. Repositáře používají k přístupu k databázi třídu poděděnou od DbContext, s tím souvisí i přistup k uloženým datům. Ten je realizován pomocí atributů typu DbSet<T>, kde T je jeden z námi definovaných doménových typů, třídy DbContext. Třída DbSet přitom implementuje rozhraní IQueryable. To umožňuje dotazování se nad atributy tohoto typu pomocí technologie Linq to Entities [17]. Metoda Save Metoda Save obsahuje funkcionalitu, která je spojená s přidáváním a editací záznamů daného datového typu. Protože tato metoda obsahuje funkcionalitu pro přidávání i editaci, je třeba rozhodnout, co se má s danou instancí provést. Pokud používáme automaticky generované klíče, tak nám stačí porovnat hodnotu primárního klíče proti defaultní hodnotě daného datového typu. Pokud se porovnávané hodnoty rovnají, tak chceme přidávat novou instanci. V opačném případě stačí nastavit atribut State spravované instance na Modified, což je jedna z hodnot výčtového typu EntityState. Atribut State určuje stav dané instance vůči hodnotám uloženým v databázi. Rozhodování se na základě porovnávání vůči defaultní hodnotě není možné v případě, kdy nepoužíváme automaticky generované klíče. Poté je potřeba zkontrolovat, zda-li databáze obsahuje instanci s daným klíčem. Tehdy nejde provést uložení pomocí změny atributu State, jelikož v tom případě bychom měli v databázi dvě instance se stejným klíčem. To z toho důvodu, že jsme Entity Frameworku dali novou instanci daného datového typu, ale neřekli mu, jaký řádek v databázi má touto instancí nahradit. Funkční řešení tohoto problému spočívá v aktualizaci hodnot pomocí explicitního přepsání, viz obrázek 20. Třída Record na tomto obrázku zastupuje libovolný doménový typ, který nemá automaticky generovaný klíč. 42

Obrázek 20: Kód metody korektně ukládající instance třídy Record Metoda Delete Metoda Delete, jak její název napovídá, obsahuje funkcionalitu spojenou s mazáním dané instance z databáze. Metoda Commit Metody Save a Delete volají k manipulaci s daty metody třídy DbSet. Tato volání fungují v tzv. Unit Of Work, což je kolekce dat, s kterými v rámci probíhajícího dotazu pracujeme. Změny provedené pomocí volání metod třídy DbSet se nepropagují rovnou do databáze, ale ukládají se pouze lokálně. K tomu aby se provedené změny uložily do databáze, je nutné explicitně zavolat virtuální metodu SaveChanges třídy poděděné od DbContext. Volání této metody v sobě zahrnuje transakční zpracování. Metoda Commit v naší aplikaci obsahuje pouze volání metody SaveChanges. 5.4.1.3 Filtrování dat Repositáře, které byly popsány v předešlé kapitole, poskytují funkcionalitu potřebnou pro ukládání a mazání instancí daného datové typu. Co repositáře ve výsledné aplikaci neobsahují, je funkcionalita pro získání instance datového typu na základě znalosti jejího primárního klíče. Místo toho nám poskytují atribut, který implementuje rozhraní IQueryable. Díky implementaci rozhraní IQueryable se můžeme nad drženými daty dotazovat pomocí Linq to Entities, a tak získat i námi požadovanou proměnou daného datového typu. Nejjednoduššími způsoby, jak získat jedinou instanci daného datového typu splňující danou podmínku, jsou volání metod FirstOrDefault a SingleOrDefault. Volání metody FirstOrDefault nám vrací první záznam splňující danou podmínku případně defaultní hodnotu. Metoda SingleOrDefault navíc ještě zkontroluje, že kolekce dat, na kterou se dotazujeme, obsahuje maximálně jeden záznam splňující definovanou podmínku. Z toho plyne fakt, že metoda SingleOrDefault je pomalejší, ale kontroluje nám konzistenci uložených dat. 5.4.2 Použité JavaScriptové knihovny Pomocí kódu napsaného v jazyce JavaScript je možné do aplikace přidat další možnosti interakce s uživatelem. Protože je tato interakce často používaná, existuje řada JavaScriptových knihoven implementujících rozsáhlou funkcionalitu. Mezi tyto knihovny patří například jquery, jquery UI a prettyphoto. 43

5.4.2.1 jquery a jquery UI Frameworky jquery a jquery UI byly použity v aplikaci například ke zprovoznění menu, fotogalerie a záložek. 5.4.2.2 CkEditor a Core Labs Five FileManager Jedním ze stanovených cílů je integrace textového, neboli WYSIWYG (což je zkratka anglických slov What You See Is What You Get) editoru. WYSIWYG editory jsou na internetu dostupné ve formě JavaScriptových knihoven. Jedním z editorů je volně šiřitelný CkEditor, který definuje i rozhraní, pomocí kterého může komunikovat se správcem souborů, jehož integrace je také jedním ze stanovených cílů. CkEditor vychází z FCkEditoru, jehož součástí byl i požadovaný správce souborů. V současnosti je na internetu dostupná knihovna FkEditor, což je správce souborů od tvůrců CkEditoru. Problém spojený s použitím tohoto správce souborů spočívá v tom, že není volně šiřitelný, což vedlo k použití jiného, volně šiřitelného správce souborů. Tím je správce souborů od Core Five Labs [14], který poskytuje veškerou potřebnou funkčnosti. Každý oprávněný uživatel může pomocí správce souborů spravovat pouze ve složce, která je pro správu dostupná pouze jemu. Tyto složky jsou umístěny ve složce /userfiles/*/data, kde hvězdička zastupuje uživatelské jméno daného uživatele. Použitý správce souborů, navzdory stanoveným cílům, neobsahuje českou lokalizaci. Vzhledem k tomu, že znalost anglického jazyka potřebná pro práci s ním je minimální, nebyla česká lokalizace implementována ani z naší strany. To především z důvodu časové náročnosti. 5.4.2.3 jquery Form Plugin jquery Form Plugin [22] je v aplikaci použit v modulech DocumentPlugin a MediaPlugin k asynchronnímu nahrávání dat na server. 5.4.3 Značkovací jazyk a kaskádové styly Kvůli kompatibilitě aplikace se staršími prohlížeči byl ve všech modulech aplikace jako značkovací jazyk použit jazyk XHTML ve verzi 1.0 Strict. K popisu způsobu zobrazení jednotlivých XHTML prvků aplikace byl využit jazyk CSS3. 5.5 BaseModule V této kapitole si probereme jednotlivé jmenné prostory definované v projektech tvořících modul BaseModule. 5.5.1 Projekt BaseDomain Projekt Domain neobsahuje pouze definice tříd určujících business logiku hlavního modulu ale i definice rozhraní repositářů a jejich konkrétní implementace. 44

5.5.1.1 BaseDomain.Entity Součástí tohoto jmenného prostoru jsou doménové typy potřebné pro požadovanou funkčnost modulu BaseModule. Konkrétně jde o třídy: Article, BaseProfile, EmployeeProfile, Event, Package, Page, PageCategory, Position, Role, RoleSetupPackage, Session, Subject, User. Dále pak o výčtové typy: PageCategorySort, Sex a PositionType. Popis jednotlivých výčtových typů, tříd a jejich atributů je dostupný ve vygenerované dokumentaci v příloze A. Vygenerovaná dokumentace obsahuje i informace o ostatních výčtových typech, třídách a rozhraních definovaných v celé aplikaci. Poznamenejme, že třídy User, Role a Session, jsou používány v našich implementacích providerů. Třída BaseProfile je abstraktní a slouží jako předek třídy EmployeeProfile. Třída BaseProfile je definována z důvodu možného rozšíření aplikace o třídu StudentProfile, která by obsahovala informace o konkrétním studentovi. Třída Package reprezentuje balíček zahrnující funkčnost nad daným datovým typem. A třída RoleSetupPackage definuje vazbu mezi rolemi a balíčky. Součástí této vazby jsou informace o oprávnění, které má uživatel v dané roli k tomuto balíčku. 5.5.1.2 BaseDomain.Abstract Součástí jmenného prostoru BaseDomain.Abstract jsou definice rozhraní (IArticleRepository, IEmployeeProfileRepository, IEventRepository, IPackageRepository, IPageRepository, IPageCategoryRepository, IPositionRepository, IRoleRepository, ISessionRepository, ISubjectRepository, IUserRepository), jejichž konkrétní implementace definují funkčnost pro manipulaci s doménovými typy definovanými ve jmenném prostoru BaseDomain.Entity v databázi. Důvodem definice těchto rozhraní je použití oddělení závislostí, které jsme řešili v kapitole 4.1. 5.5.1.3 BaseDomain.Concrete Jmenný prostor BaseDomain.Concrete obsahuje konkrétní implementace všech rozhraní ze jmenného prostoru BaseDomain.Abstract. Dále tento jmenný prostor obsahuje třídu BaseModuleDbContext, která je poděděná od třídy DbContext. Toto třída reprezentuje připojení k databázi tak, jak bylo zmíněno v kapitole 5.4.1, a obsahuje definice relací mezi doménovými typy z jmenného prostoru BaseDomain.Entity. 5.5.1.4 BaseDomain.ValidationAttribute Ve jmenném prostoru BaseDomain.ValidatonAttribute jsou definovány naše validační atributy. Konkrétně jde o validační atributy: KeywordsAttribute a DateTimeGreaterThanOrEqualToAttribute. Vlastní validační atributy byly v aplikaci použity k validaci počtu klíčových slov a k porovnání dat uvedených u akcí školy. 45

Implementace validačního atributu Pro validaci dat námi definovaným atributem, po jejich odeslání na server, nám stačí definovat třídu poděděnou od ValidationAttribute. Třída ValidationAttribute obsahuje jedinou virtuální metodu IsValid, jejíž kód určuje validační logiku. Kód metody IsValid je automaticky proveden při modelbindingu. Pokud chceme uživateli poskytnout i komfort v podobě tzv. client-side validace, je třeba třídu obsahující definici validačního atributu podědit zároveň i od rozhraní IClientValidatable. Rozhraní IClientValidatable definuje pouze metodu GetClientValidationRules, pomocí které vracíme validační pravidla, která mají být použita JavaScriptovým kódem. K zprovoznění client-side validace je třeba ještě napsat JavaScriptový kód, který bude obstarávat validaci na straně uživatele. Tento kód je třeba vložit do stránky, na které se má validace provádět. Detailní návod k vytvoření vlastního validačního atributu lze nalézt na osobním blogu Nicka Olsena [32]. 5.5.2 BaseWeb Projekt BaseWeb je hlavním projektem celé aplikace. To z toho důvodu, že obsahuje funkčnost pro načítání přídavných modulů a správu vazeb potřebných k vkládání závislostí. 5.5.2.1 BaseWeb Jmenný prostor BaseWeb obsahuje jedinou třídu, a to MvcApplication. Ta je poděděná od HttpApplication a představuje vstupní bod celé aplikace. Třída MvcApplication má za úkol registrování všech směrovacích pravidel a nastavení Elmahu. Nastavení směrovacích pravidel Třída poděděná od MvcApplication obsahuje metodu Application_Start, jejíž kód se spouští automaticky při startu aplikace. Obrázek 21: Kód volající metody, které registrují směrovací pravidla V rámci metody Application_Start se volá kód registrující směrovací pravidla definovaná ve všech referencovaných třídách, které jsou poděděny od třídy AreaRegistration viz volání metody AreaRegistration.RegisterAllAreas na obrázku 21, a směrovací pravidla určená hlavní aplikací, ty jsou registrovány v metodě RegisterRoutes. Elmah O knihovně Elmah jsme psali již v kapitole 4.4.1. Nyní se zaměříme na to, jak jí úspěšně přidat do aplikace. 46

Pro spuštění Elmahu stačí do aplikace přidat potřebné reference a provést změny v konfiguračním souboru. Pomocí těchto změn se Elmah zaregistruje jako modul pro logování všech neodchycených výjimek. Všechny potřebné změny za nás může udělat opět extension NuGet. Díky němu můžeme přidat Elmah do aplikace pomocí pár kliknutí. Obrázek 22: Metoda filtrující vyhozené výjimky Elmah obsahuje i funkcionalitu pro posílání e-mailů pří výskytu chyby. Běžně však nechceme dostávat e-maily upozorňující nás na chyby typu špatně zadané adresy. Z toho důvodu lze nastavit filtrování výjimek tak, aby nám byly odesílané chyby pouze požadovaného typu. Toto nastavení lze definovat v metodě ErrorMail_Filtering, která je vidět na předešlém obrázku. Uvedený kód filtruje výjimky tak, že nám nejsou posílány e-maily o chybách typu 404, tedy soubor nenalezen. 5.5.2.2 BaseWeb.App_Start Jmenný prostor obsahuje NinjectWebCommon třídu, jejíž kód je spouštěn při startu aplikace, což je nastaveno pomocí třídy WebActivator. Dále pak třídu poděděnou od třídy RazorViewEngine. NinjectWebCommon Statická třída NinjectWebCommon registruje Ninject jako dependency resolver. Dále pak obsahuje statickou metodu RegisterServicer, která registruje potřebné vazby pro vkládání závislostí a načítá přídavné moduly na základě dané jmenné konvence. Kvůli načítání přídavných modulů musí výsledná aplikace běžet s oprávněním Full trust, což odpovídá oprávnění Full u ASP.NET. Vkládání závislostí Aby mohly být závislosti Ninjectem vkládány, musí být Ninject nastaven jako tzv. dependency resolver. Díky tomuto nastavení má Ninject na starosti vkládání závislostí nejen do controllerů, ale i do jiných částí aplikace. Těmi jsou v naší aplikaci například providery. K tomu, abychom Ninject nastavili jako dependency revolver, je nejlepší použít extension Visual Studia NuGet. NuGet za nás v tomto případě vygeneruje potřebný kód. Kód vygenerovaný NuGetem tvoří kostru třídy NinjectWebModule. Jedním z důvodu, proč jsme se v kapitole 4.2.4 rozhodli pro použití Ninjectu, byla i pokročilejší správa životního cyklu vkládaných objektů, než je tomu u frameworku MEF. 47

Správa životního cyklu Často chceme, aby instance vkládaná pomocí Ninject byla sdílena více objekty. Toto chování je vhodné v případě, kdy vkládaná instance má například velké paměťové nároky. Defaultní chování Ninjectu dosazuje vždy novou instanci. Pro změnu tohoto chování je potřeba u definice bindingu uvést rozsah jeho platnosti. V rámci výsledné aplikace se používají dva rozsahy platnosti: InRequestScope Ninject dosazuje do všech objektů stejnou instanci vkládaného typu v rámci konkrétního dotazu InTrainsientScope odpovídá defaultnímu chování, tehdy Ninject dosazuje vždy novou instanci vkládaného typu Chování definované pomocí volání metody InRequestScope je vhodné k definici vazeb repositářů a třídy poděděné od DbContextu, která nám definuje Unit of Work, v případě, že se instance těchto tříd vkládají do objektů, jejichž životní cyklus je vázán na jeden požadavek. PluggableRazorViewEngine View engine, kterým je v našem případě Razor, hledá pohled daného jména na základě jmenných konvencí. Výchozí jmenné konvence však nejsou definovány pro použití v modulárních aplikacích, kde pohledy jednotlivých modulů jsou uloženy do struktury reprezentující strukturu aplikace. Strukturu, kterou dodržují naše pohledy, jsme popsali v kapitole 5.2. Kvůli tomu jsou ve výsledné aplikaci předefinovány konvence, na jejich základě je požadovaný pohled hledán. K předefinování defaultních konvencí stačí v rámci hlavního modulu podědit třídu RazorViewEngine viz blog Longa Leho [30]. 5.5.2.3 BaseWeb.Controllers Jmenný prostor BaseWeb.Controllers obsahuje všechny controllery hlavního modulu. Konkrétně obsahuje následující controllery: AccountController, ArticleController, EventController, ErrorCntroller, MenuController, PageCategoryController, PositionController, RoleController, SubjectController. Všechny controllery, kromě AccountControlleru a MenuControlleru, obsahují funkcionalitu pro správu a prezentaci doménového typu s názvem odpovídajícím názvu controlleru. Například ArticleController obsahuje funkcionalitu potřebnou ke správě doménového typu Article. Ke všem veřejným metodám controllerů, které mají návratový typ ViewResult nebo PartialViewResult, existují příslušné pohledy. Ty jsou uloženy ve složce Views. AccountController AccountController je součástí nové aplikace napsané v ASP.NET MVC vytvořené pomocí Visual Studia. V naší aplikaci je z tohoto controlleru ponechaná pouze funkčnost zajišťující přihlašování a odhlašování uživatelů. MenuController MenuControlleru obsahuje pouze metody Menu a AdminMenu. 48

Metoda Menu generuje menu pro veřejně dostupnou část aplikace. V tomto menu jsou zobrazeny jak odkazy na přehledy různých doménových typů, tak odkazy na stránky zobrazující data konkrétní instance třídy Page. Metoda AdminMenu generuje menu pro zabezpečenou část aplikace. Podoba tohoto menu záleží na oprávněních daného uživatele. Pokud aplikaci rozšíříme o nový balíček, tak je potřeba uložit do databáze nový záznam typu Package. Na základě informací obsažených v tomto záznamu se poté bude zobrazovat odkaz na tento balíček v menu jak veřejně přístupné, tak i zabezpečené části aplikace. Konkrétní informace o atributech a jejich významu jsou dostupné ve vygenerované dokumentaci v příloze A. Kontrola oprávnění uživatele je drahá operace, z toho důvodu jsou tyto hodnoty v rámci MenuControlleru cachovány. Cachování Nejen ve webových aplikacích je často využívanou technikou cachování. To se používá v případě, že chceme mít rychleji dostupná často požadovaná data. Data uložená v cache jsou automaticky mazána. Mazání probíhá v konkrétním čase, nebo po uplynutí timeoutu od posledního použití uložených hodnot. Pokud uložená data chceme smazat manuálně, musíme to udělat pomocí přiřazení null hodnoty danému klíči, nebo resetem celé cache, který se provede pomocí volání metody HttpRuntime.Close(). 5.5.2.4 BaseWeb.HtmlHelpers Jmenný prostor BaseWeb.HtmlHelpers je tvořen statickými třídami. Ty obsahují definice extension metod. Pomocí těchto metod je možné vytvářet nové html helpery. Všechny html helpery nadefinované v tomto jmenném prostoru jsou použity ke generování menu, případně jiné formy navigace využité ve veřejně dostupné části aplikace. 5.5.2.5 BaseWeb.Models Ve jmenném prostoru BaseWeb.Models jsou definovány třídy potřebné k tomu, aby byly všechny pohledy silně typové. Nejčastěji používanou třídou ze jmenného prostoru BaseWeb.Models je třída PagingInfo. Ta drží informace potřebné k tvorbě stránkovaní záznamů daného datového typu. 5.5.2.6 BaseWeb.Providers V kapitole 4.3.2 jsme uvedli důvody, proč nejsou defaultní implementace providerů vhodné pro použití v naší aplikaci. Aby aplikace používala naše implementace providerů, je potřeba upravit odpovídající uzly soubory web.config. Na následujícím obrázku je vidět kód nastavující používaný RoleProvider na naší implementaci. Použité implementace providerů vycházejí ze vzorových implementací, ty jsou dostupné na stránkách http://msdn.microsoft.com/en-us/. V aplikaci jsou tyto providery implementovány ve jmenném prostoru BaseWeb.Providers. 49

Obrázek 23: Nastavení defaultní RoleProvideru na MsSqlRoleProvideru Ke komunikaci s databází používají providery Entity Framework a mají definované relace na záznamy ostatních datových typů. Díky definici relací je možné používání navigačních proměnných k získání informací o autorovi daného záznamu. Kromě Entity Frameworku je v našich implementacích použitá i technika vkládání závislostí, což umožňuje testování providerů. Životní cyklus a vkládání závislostí V kapitole 5.5.2.2 jsme uvedli, že pro vkládání repositářů a tříd poděděných od DbContextu používáme způsob vkládání závislostí, který inicializuje instanci daného objektu pouze jednou za dotaz. Tento způsob vkládání je vhodný v případě, že životní cyklus objektu, do kterého vkládáme, odpovídá životnímu cyklu požadavku. To neplatí pro providery, jejichž životní cyklus není vázán na jeden požadavek. S použitím vkládání v rámci konstruktoru a chování definovaného pomocí volání InRequestScope bychom měli problémy. Stávalo by se nám, že v rámci stále platného provideru držíme referenci na repositář, který byl již Ninjectem zdisposován. Proto providery fungují buďto nad explicitně určenými instancemi repositářů, což je vhodné pro účely testování, anebo je vkládána nová instance požadovaného repositáře při volání libovolné metody jednoho z providerů. Vkládání nových instancí do každé metody je používané při standardním běhu aplikace. Díky tomu máme jistotu, že Unit of Work, o nichž jsme se bavili v kapitole 5.4.1.2, používané providery neobsahují zastaralá data. 5.5.3 BaseUnitTest Projekt BaseUnitTest je tvořen unit testy testujícími funkčnost controllerů, providerů, směrovacích pravidel a html helperu definovaných v projektu BaseWeb. Dále unit testy tohoto projektu testující server-side funkčnost validačních atributů ze jmenného prostoru BaseDomain.ValidationAttribute. 5.5.3.1 BaseUnitTest.Controllers Jmenný prostor BaseUnitTest.Controllers obsahuje třídy testující všechny action metody controllerů ze jmenného prostoru BaseWeb.Controllers. 50

5.5.3.2 BaseUnitTest.HtmlHelpers Třídy jmenného prostoru BaseUnitTest.HtmlHelpers obsahují testy pro html helpery definované ve jmenném prostoru BaseWeb.HtmlHelpers. 5.5.3.3 BaseUnitTest.Providers Jmenný prostor BaseUnitTest.Providers obsahuje testy pro většinu metod providerů definovaných ve jmenném prostoru BaseWeb.Providers. Některé metody, například MembershipProvider.GetAllUser a MembershipProvider.GetUser, ve jmenném prostoru BaseWeb.Providers nejdou otestovat z toho důvodu, že jejich funkčnost je závislá na komponentách, které nejsou v naší implementaci vkládány pomocí mechanismu vkládání závislostí. Z toho důvodu jsou pro otestování těchto metod vhodné spíše integration testy, o nichž jsme se bavili v kapitole 4.5.1. K testování metod, které jsou závislé pouze na jiných metodách daného provideru, byl použit framework Microsoft Fakes, který umožňuje za běhu aplikace předefinovat kód vybraných metod. 5.5.3.4 BaseUnitTest.Routing Součástí jmenného prostoru BaseUnitTest.Routing je kromě třídy testující směrovací pravidla hlavního modulu i třída RoutingTestHelper. Ta obsahuje metodu definující falešný HttpContext pomocí nějž je možné testovat směrovací pravidla definovaná v aplikaci. Dále třída RoutingTestHelper obsahuje metody zjednodušující testování směrovacích pravidel libovolného modulu. Kód těchto metod vychází z příkladů dostupných v Pro ASP.NET MVC 3 Framework [17]. 5.5.3.5 BaseUnitTest.UnitTestHelper Jmenný prostor BaseUnitTest.UnitTestHelper obsahuje jedinou třídu. Ta definuje generickou třídu, která je používána pro testování validačních atributů porovnávajících hodnoty více prvků. 5.5.3.6 BaseUnitTest.ValidationAttribute Ve jmenném prostoru BaseUnitTest.ValidationAttribute jsou definované třídy, které testují správnost server-side validace atributů definovaných ve jmenném prostoru BaseDomain.ValidationAttribute. 5.6 DocumentModule DocumentModule rozšiřuje funkčnost hlavního modulu o správu úložiště vzdělávacích materiálů. K tomu je potřeba definovat novou business i aplikační logiku a unit testy, které tuto funkčnost otestují. 5.6.1 DocumentDomain V projektu DocumentDomain jsou definované nové doménové typy a s nimi související repositáře, které s těmito typy manipulují. 51

5.6.1.1 DocumentDomain.Entity Jmenný prostor DocumentDomain.Entity obsahuje definice 3 doménových typů: EducationProgram, SubjectArea a Document. Stejně jako v případě hlavního modulu jsou popisy jednotlivých rozhraní, tříd modulu DocumentModule dostupné ve vygenerované dokumentaci v příloze A. Všechny tyto doménové typy jsou potřeba pro správu vzdělávacích materiálů. Vzdělávací materiály jsou reprezentovány třídou Document. Třídy EducationProgram a SubjectArea jsou používány pro účely filtrování vzdělávacích materiálů, což byl jeden z požadavků stanovených v kapitole 1.2.2. 5.6.1.2 DocumentDomain.Abstract Jmenný prostor DocumentDomain.Abstract obsahuje rozhraní: IEducationProgramRepository, ISubjectAreaRepository a IDocumentRepository. Tyto rozhraní definují metody potřebné pro správu doménových typů ze jmenného prostoru DocumentDomain.Entity. 5.6.1.3 DocumentDomain.Concrete Jmenný prostor DocumentDomain.Concrete obsahuje konkrétní implementace všech rozhraní ze jmenného prostoru DocumentDomain.Abstract. Dále tento jmenný prostor obsahuje třídu DocumentDbContext, která dědí od třídy BaseModuleDbContext definované ve jmenném prostoru BaseDomain tak, jak bylo popsáno v kapitole 5.4.1.1. 5.6.2 DocumentWebPlugin Projekt DocumentWebPlugin obsahuje controllery, které představují aplikační logiku nutnou ke správě doménových typů definovaných ve jmenném prostoru DocumentDomain.Entity. Dále tento projekt obsahuje definici směrovacích pravidel specifických pro tento modul a třídu, pomocí které jsou registrovány vazby pro vkládání závislostí. Tyto vazby jsou registrovány v rámci dependency injectoru hlavního modulu. 5.6.2.1 DocumentWebPlugin Jmenný prostor DocumentWebPlugin obsahuje jedinou třídu a DocumentPluginAreaRegistration. Účel této třídy je definice směrovacích pravidel specifických pro modul DocumentModule. Definice směrovacích pravidel Jak bylo řečeno v rámci kapitoly 5.5.2.1, metoda Application_Start, která je obsažena třídě MvcApplication ve jmenném prostoru BaseWeb, registruje všechna směrovací pravidla, která jsou obsažena v referencovaných třídách, poděděných od AreaRegistration. Důležité je, aby třída poděděná od AreaRegistration byla součástí kořenového jmenného prostoru projektu tak, jak je vidět na obrázku 24, kde definujeme směrovací pravidla pro oblast s názvem Plugin. To kvůli tomu, že vůči 52

jmennému prostoru, v němž je implementovaná třída poděděná od AreaRegistration, se hledají controllery daného projektu. Obrázek 24: Implementace třídy poděděné od AreaRegistration 5.6.2.2 DocumentWebPlugin.Start_Up Jmenný prostor DocumentWebPlugin.Start_Up obsahuje pouze třídu DocumentNinjectModule. Třída DocumentNinjectModule je poděděná od třídy NinjectModule, která obsahuje virtuální metodu Load. Metoda Load je automaticky volána ve chvíli, kdy je daný projekt načten hlavním modulem. Pomocí zmíněné metody Load třídy poděděné od NinjectModule lze registrovat bindingy v rámci dependecy resolveru hlavního modulu. Díky tomu nemusí ani přídavné moduly obsahovat těsné vazby. 5.6.2.3 DocumentWebPlugin.Controllers Ve jmenném prostoru DocumentWebPlugin.Controllers jsou definovány controllery, které obsahují aplikační logiku pro správu doménových typů, které jsou definovány ve jmenném prostoru DocumentDomain.Entity. Konkrétně jde o controllery EducationProgramController, SubjectAreaController a DocumentController. 53

K načítání vzdělávacích materiálů je použita knihovna jquery Form Plugin [22]. Díky tomu probíhá toto načítání asynchronně a uživatel je průběžně informován o jeho průběhu. 5.6.2.4 DocumentWebPlugin.Models Jmenný prostor DocumentWebPlugin.Models obsahuje jedinou třídu. Ta je použita pro potřeby model-bindingu při filtrování vzdělávacích materiálů. 5.6.3 DocumentUnitTest Projekt DocumentUnitTest obsahuje pouze dva vnořené jmenné prostory. Těmi jsou jmenné prostory DocumentUnitTest.Controllers a DocumentUnitTest.Routing. 5.6.3.1 DocumentUnitTest.Controllers Obdobně jako jmenný prostor BaseUnitTest.Controllers i DocumentUnitTest.Controllers obsahuje unit testy testující jednotlivé action metody controllerů. V tomto případě to jsou metody controllerů definovaných ve jmenném prostoru DocumentWebPlugin.Controllers. 5.6.3.2 DocumentUnitTest.Routing Jmenný prostor DocumentUnitTest.Routing obsahuje jedinou třídu. Ta testuje směrovací pravidla definovaná ve třídě DocumentPluginAreaRegistration. 5.7 MediaModule Modul MediaModule rozšiřuje funkčnost hlavního modulu o správu fotogalerií a videogalerií. 5.7.1 MediaDomain V projektu MediaDomain jsou definované nové doménové typy, rozhraní a konkrétní implementace repositářů. 5.7.1.1 MediaDomain.Entity Jmenný prostor MediaDomain.Entity obsahuje doménové typy: Photo, Photogallery a Videogallery. 5.7.1.2 MediaDomain.Abstract Ve jmenném prostoru MediaDomain.Abstract jsou definovány rozhraní: IPhotoRepository, IPhotogalleryRepository a IVideoRepository. Tyto rozhraní definují metody potřebné pro správu odpovídajících doménových typů. 54

5.7.1.3 MediaDomain.Concrete Jmenný prostor MediaDomain.Concrete obsahuje konkrétní implementace všech rozhraní ze jmenného prostoru MediaDomain.Abstract. 5.7.2 MediaWebPlugin Projekt MediaWebPlugin obsahuje controllery, které definují aplikační logiku pro správu doménových typu definovaných ve jmenném prostoru MediaDomain. Konkrétně jde o PhotoController, PhotogalleryController a VideoController. Stejně jako v případě projektu DocumentWebPlugin obsahuje projekt MediaWebPlugin definici směrovacích pravidel specifických pro tento modul a třídu, pomocí které jsou registrovány vazby pro vkládání závislostí u dependency injectoru hlavního modulu. 5.7.2.1 MediaWebPlugin Jmenný prostor MediaWebPlugin obsahuje pouze třídu MediaPluginAreaRegistration, která definuje směrovací pravidla pro modul MediaModule. 5.7.2.2 MediaWebPlugin.Start_Up Jmenný prostor MediaWebPlugin.Start_Up obsahuje třídu MediaNinjectModule. Tato třída je poděděná od NinjectModule a obsahuje metodu Load. Pomocí metody Load třídy poděděné od NinjectModule se registrují bindingy v rámci dependecy resolveru hlavního modulu. 5.7.2.3 DocumentWebPlugin.Controllers Ve jmenném prostoru DocumentWebPlugin.Controllers jsou definovány controllery (PhotoController, PhotogalleryController a VideoController), které obsahují aplikační logiku pro správu doménových typů definovaných ve jmenném prostoru DocumentDomain.Entity. K dávkovému načítání fotografií je stejně jako v případě vzdělávacích materiálů použita knihovna jquery Form Plugin [22]. Použitím této knihovny můžeme fotografie načítat asynchronně a zároveň informovat uživatele o aktuálním průběhu. Pro účely procházení fotografií v rámci dané fotogalerie je použita JavaScriptová knihovna prettyphoto [33]. 5.7.2.4 MediaWebPlugin.Models Jmenný prostor MediaWebPlugin.Models obsahuje třídy reprezentující data předávaná do příslušných view, nebo používané při model-bindingu. 5.7.3 MediaUnitTest Projekt MediaUnitTest obsahuje pouze dva vnořené jmenné prostory. Těmi jsou jmenné prostory MediaUnitTest.Controllers a MediaUnitTest.Routing. 55

5.7.3.1 MediaUnitTest.Controllers Jmenný prostor MediaUnitTest.Controllers obsahuje unit testy testující jednotlivé action metody všech controllerů definovaných ve jmenném prostoru DocumentWebPlugin.Controllers. 5.7.3.2 MediaUnitTest.Routing Jmenný prostor MediaUnitTest.Routing obsahuje jedinou třídu. Ta testuje směrovací pravidla definovaná ve třídě MediaPluginAreaRegistration. 56

6 Uživatelská dokumentace V této kapitole popíšeme způsob, jakým s aplikací pracují její uživatelé. Aplikace je složená z veřejně přístupné části, která slouží k prezentaci spravovaného obsahu. Druhá část slouží ke správě tohoto obsahu. Rozložení stránky veřejné části aplikace se mírně liší od rozložení stránky použitého v tzv. backendu, což je název používaný pro část aplikace umožňující správu obsahu. Rozložení obou částí aplikace jsou vidět na obrázcích 25 a 26. 6.1 Rozložení stránky ve veřejné části aplikace K procházení obsahu obsahuje veřejná část aplikace 4 menu. Tato menu jsou rozdělena do skupin škola a speciálně pedagogické centrum. Na stránce je vždy zobrazena pouze jedna skupina, na obrázku 25 je to skupina škola. Implicitně je zobrazena ta skupina, ve které je odkaz na adresu aktuálního požadavku. Na skupinu speciálně pedagogické centrum se uživatel může dostat pomocí odkazu v pravém sloupci stránky. Obrázek 25: Rozložení stránky ve veřejně přístupné části aplikace Jednotlivá menu, umístěná v levém sloupci, jsou automaticky generována. Mohou obsahovat odkazy na archivy spravovaných typů dat, nebo na stránky statického charakteru. Stránky statického charakteru jsou sdružovány do větších skupin. Na obrázku 25 je taková skupina reprezentována například odkazem Kategorie škola. Po kliknutí na tento odkaz nedojde k přesměrování na odpovídající adresu, ale dojde k rozbalení vloženého podmenu, které obsahuje odkazy na všechny stránky spadající do této kategorie. 57

Záznam hlavního menu, který obsahuje odkaz s adresou aktuálního požadavku je implicitně zvýrazněn, viz Aktuality na obrázku 25. Prostřední sloupec obsahuje obsah odpovídající aktuálnímu požadavku. V případě, že budeme popisovat funkčnost jednotlivých balíčků, budou příslušné obrázky obsahovat pouze výřez tohoto sloupce. To z toho důvodu, že podoba ostatních sloupců se mění pouze do té podoby, která je popsaná v této kapitole. Pravý sloupec obsahuje odkazy, pomocí nichž lze přepínat mezi zobrazením jednotlivých skupin menu tak, jak bylo řečeno dříve. Dále pravý sloupec obsahuje kalendář událostí školy, který umožňuje procházení bez potřeby načítání celé stránky. Pod kalendářem je vykreslen formulář, pomocí nějž se lze přihlásit do backendu aplikace. V případě, že jsou stránky prohlíženy přihlášeným uživatelem, je, místo přihlašovacího formuláře, vykreslena informace o tom, že je uživatel přihlášen a tlačítko, pomocí kterého se může uživatel odhlásit. 6.2 Rozložení stránky v backendu aplikace Rozložení stránky backendu aplikace není tvořeno 3 sloupci tak, jako je tomu ve veřejné části aplikace. To z toho důvodu, že v backendu aplikace nepotřebujeme funkčnost, kterou obsahoval pravý sloupec ve veřejné části aplikace. Obrázek 26: Rozložení stránky v backendu alikace 58

Navigace v backendu aplikace probíhá pomocí odkazů v menu, které tvoří levý sloupec. Jednotlivé odkazy vedou na seznamy všech záznamů odpovídajících datových typů. Pravý sloupec obsahuje obsah odpovídající aktuálnímu požadavku. Stejně jako v případě veřejné části aplikace budou následující obrázky popisující funkčnost jednotlivých balíčku obsahovat pouze výřez tohoto sloupce. V případě, že se chce uživatel z backendu aplikace dostat do její veřejné části, stačí, aby kliknul na logo školy. To je vhodné například v případě, kdy se chce odhlásit, což může udělat v pravém sloupci veřejné části aplikace tak, jak bylo popsáno v kapitole 6.1. 6.3 Popis práce s jednotlivými balíčky Balíčkem v naší aplikaci myslíme funkcionalitu spojenou se správou jednoho datového typu, tím mohou být například aktuality, události a stránky statického charakteru. Následující kapitoly budou obsahovat popis správy všech datových typů. Výběr spravovaného datového typu lze provést pomocí odkazů z menu umístěného v levém sloupci backendu aplikace. 6.3.1 Role Role jsou přiřazovány jednotlivým uživatelům. Díky tomu je možné omezit přístup jednotlivých uživatelů k vybraným balíčkům, případně jim dát možnost editace pouze jejich záznamů daného datového typu. Na obrázku 27 je vidět obsah pravého sloupce na stránce obsahující seznam všech definovaných rolí. Obrázek 27: Přehled všech definovaných rolí Pro vytvoření nové role slouží stránka, na kterou vede odkaz Nový záznam na předešlém obrázku, obsah pravého sloupce této stránky je vidět na následujícím obrázku. Pro vytvoření nové role stačí zadat její název a kliknout na tlačítko odeslat. V případě, že se chceme z dané stránky pouze vrátit na seznam všech uložených rolí, stačí nám kliknout na odkaz Zpět na přehled. Odkaz Upravit vede na stránku obsahující formulář potřebný pro upravení názvu dané role. Ostatní tlačítka jsou stejná jako v případě vkládání nové role. To platí i pro ostatní metody, které umožňují vkládání a editaci záznamů libovolného datového typu. 59

Obrázek 28: Obsah pravého sloupce na stránce umožňující vložení nové role Pomocí odkazu Oprávnění se uživatel dostane na stránku, která umožňuje změnu oprávnění role ke všem balíčkům v aplikaci. Zaškrtávací boxy ve druhém sloupci tabulky definují, zda má uživatel, který má přiřazenou pouze tuto roli, oprávnění ke správě daného datového typu. Zaškrtávací boxy v posledním sloupci určují, zda může ten samý uživatel spravovat všechny záznamy daného datového typu, nebo jen ty záznamy, kterých je autorem. To v případě, když za názvem daného balíčku nenásleduje text říkající, že toto nastavení nebude zohledněno, viz následující obrázek. Obrázek 28: Správa oprávnění role admin Nastavení na obrázku 28 určuje, že uživatel v roli admin může spravovat všechny aktuality, dokumenty, kterých je autorem a zaměstnance. Zaměstnance navíc může spravovat bez ohledu na stav tlačítka všechny záznamy v odpovídajícím řádku. Odkaz Uživatelé vede na stránky obsahující seznam všech uživatelů, kteří mají přiřazenou danou roli. Tento seznam obsahuje u každého uživatele odkaz vedoucí na stránku umožňující správu rolí daného uživatele. Obrázek 29: Dialogové okno použité k potvrzení mazání daného záznamu Kliknutí na odkaz Smazat způsobí zobrazení dialogového okna s hláškou, která žádá uživatele o potvrzení smazání dané role, ta je zobrazena na předchozím obrázku. V případě souhlasu je vybraná role smazána. Stejný 60

postup pro mazání konkrétního záznamu je použit pro potřeby mazání všech datových typů, které jsou v aplikaci spravovány. 6.3.2 Předměty Odkaz Předměty vede na seznam všech vyučovaných předmětů. U předmětu je možné uchovávat jeho název a zkratku tohoto názvu. Přidávání, upravování a mazání předmětů funguje stejně jako v případě rolí. U daného předmětu je možné pomocí odkazu Vyučující přejít na stránku se seznamem všech učitelů, kteří daný předmět vyučují. 6.3.3 Pozice Pomocí odkazu Pozice se uživatel dostane na stránku se seznamem všech pozic. Pozice jsou na stránce děleny do tří skupin tak, aby bylo možné rozlišovat mezi pozicemi pro vedení školy, učitele a ostatní zaměstnance školy. V rámci těchto skup lze měnit pořadí jednotlivých záznamů. V tomto pořadí jsou pozice vykreslovány i ve veřejné části aplikace. Změnu pořadí lze měnit pomocí tažení celého řádku. Pro uložení provedených změn je třeba potvrdit provedené změny pomocí tlačítka Odeslat pořadí pozic viz obrázek 30. Obrázek 30: Tlačítko ukládající změněné pořadí jednotlivých záznamů Pro výběr vhodné skupiny pro danou pozici obsahují stránky k vytváření a upravování pozic seznam s přípustnými hodnotami. Kromě výběru vhodné skupiny je u pozice třeba zadat pouze její název. Pomocí odkazu Zaměstnanci, který je vidět na obrázku 30, se uživatel dostane na stránku obsahující seznam všech zaměstnanců, kteří ve škole zastávají danou pozici. 6.3.4 Zaměstnanci Odkaz Zaměstnanci v levém sloupci vede na stránku, která obsahuje seznam všech zaměstnanců. Obsah pravého sloupce je vidět na následujícím obrázku. Obrázek 31: Seznam všech sučasných a minulých zaměstnanců Význam prvních dvou sloupců je zřejmý z jejich názvů. Třetí sloupec obsahuje informaci o pozici daného zaměstnance. Dle tohoto údaje se ve veřejné 61

části aplikace, dostupné pod odkazem zaměstnanci, shlukují zaměstnanci do skupin. Chceme-li, aby se informace o daném uživateli nezobrazovaly na dané stránce, nesmí mít uživatel přiřazenou žádnou pozici. Na stránku umožňující vytvoření nového uživatele se dostaneme pomocí odkazu Nový záznam. Vytvořením nového zaměstnance zároveň vytvoříme i nového oprávněného uživatele. Tento uživatel se může přihlásit do backendu aplikace, ale nemá oprávnění žádnému k balíčku. Formulář pro vytvoření nového uživatele je podobný tomu z obrázku 28, jen obsahuje více textových polí. Ty jsou opatřeny názvy, které přesně určují význam odpovídajících polí. Pomocí odkazu Detail se dostaneme na stránku obsahující veškeré spravované informace o daném zaměstnanci. Mezi ty patří například jeho aprobace, přiřazené role a pozice ve škole. Odkaz Aprobace směruje na stránku, na které můžeme spravovat aprobace daného uživatele. Uživatel může učit libovolný předmět, který je v aplikaci uložen jako vyučovaný. Obrázek 32: Správa rolí daného uživatele Odkaz Role vede na stránku umožňující správu rolí daného uživatele, viz obrázek 32. Stejně jako v případě aprobací i u rolí mohou být uživateli přiřazeny libovolné role spravované v rámci aplikace. Díky přiřazení uživatele do nějaké role má uživatel propůjčena oprávnění této role, a může tak spravovat vybrané datové typy. Nastavení oprávnění bylo vysvětleno v předchozí kapitole. Pomocí odkazu Upravit se uživatel dostane na stránku, kde může upravit informace uchovávané u daného zaměstnance. Úprava neumožňuje změnu přihlašovacího jména daného uživatele. Heslo uživatele je možné změnit na stránce, na kterou vede odkaz Změnit heslo, který se nachází pod tlačítkem Odeslat. Zaměstnanci jsou jediný datový typ, který nejde smazat. V případě, že chceme uživateli znemožnit přístup do backendu aplikace, stačí použít odkaz Zakázat. Pomocí kliknutí na tento odkaz se provede uzamknutí uživatele. K tomu dojde i v případě, že uživatel zadá 5* špatné heslo. Obrázek 33: Tabulka obsahující odkaz pro odemknutí zamknutého zaměstnance V případě, že došlo k zamknutí zaměstnance a my mu chceme znovu povolit přístup do backendu aplikace, stačí kliknout na odkaz Povolit, ten je vidět na obrázku 33. Tento odkaz nahradil odkaz Zamknout, který se zobrazuje u odemknutých zaměstnanců. 62

6.3.5 Aktuality Pomocí odkazu Aktuality se uživatel dostane na stránkovaný seznam všech aktualit. Informace o aktuální stránce je součástí nadpisu stránky. Uživatel může procházet jednotlivé stránky pomocí odkazů umístěných pod tabulkou obsahující informace o dané podmnožině záznamů, viz následující obrázek. Obrázek 34: Stránkovaný přehled aktualit V případě, že nemá oprávnění ke všem aktualitám tak, jak bylo zmíněno v kapitole 6.3.1, mu jsou zobrazeny pouze aktuality, kterých je autorem. Uživatel může vytvářet, upravovat a mazat aktuality. Mazání probíhá pomocí dialogového okna z obrázku 29. Pro vytváření a editování aktualit má uživatel k dispozici totožný formulář, jehož součástí je i textový editor, který je vidět na obrázku 34. Pomocí textového editoru mohou uživatelé formátovat anotaci a text aktuality. Anotace aktuality se zobrazuje na úvodní stránce veřejné části aplikace, případně v archivu všech aktualit. Text stránky se zobrazuje při přechodu na detail dané aktuality. Položky Klíčová slova a Popis pro vyhledávače se na stránkách nezobrazují, ale tvoří obsah HTML tagů, které používají vyhledávače k indexování dané stránky. Položka Datum určuje datum, ke kterému se aktualita váže. Podle data jsou aktuality řazeny při zobrazení. Položka Předchozí aktualita umožňuje vytvoření vazby aktuality na aktualitu, které je již uložená. Informace o této vazbě se zobrazuje na stránce s detailem aktuality a umožňuje rychlé procházení souvisejících záznamů. Obrázek 35: Textový editor integrovaný do stránek U většiny tlačítek přítomných v nástrojové liště textového editoru je jejich účel patrný z obrázku, kterým jsou reprezentovány. Z toho důvodu se zaměříme pouze na tlačítko, které je reprezentované fotografií. Při kliknutí na toto tlačítko se uživatelům objeví dialogové okno, pomocí kterého mohou zadat parametry zobrazeného obrázku, viz obrázek 35. 63

Obrázek 35: Dialogové okno pro vkládání obrázku Položky šířka a výška určují rozměry obrázku ve výsledné stránce. Položka Alternativní text určuje text, který se uživateli zobrazí v případě, že se daný obrázek nepodaří načíst. Položky Okraje, H-Mezera, V-Mezera, Zarovnání určují ohraničení a obtékání obrázku. Nejdůležitější položkou je URL, do té mohou uživatelé buďto sami zadat URL adresu požadovaného obrázku, nebo využít tlačítka Vybrat na serveru. Stisk tohoto tlačítka způsobí otevření souborového správce, který umožňuje uživatelům na server nahrát nový obrázek a poté ho vybrat k zobrazení na stránkách. Práce se správcem souborů bude popsána v následujícím odstavci. Ostatní záložky tohoto dialogového okna obsahují funkcionalitu, kterou uživatelé s největší pravděpodobností nevyužijí, a proto zde nebude popsána. Obrázek 36: Integrovaný správce souborů K procházení adresářové struktury slouží ve správci souborů primárně levý sloupec. V případě, že naposled uživatel v levém sloupci vybral konkrétní soubor a ne složku, může pomocí menu, které se zobrazí pod náhledem souboru provést 4 základní operace. Ty jsou kromě textového popisu ilustrovány i obrázky, takže nehrozí, že by uživatel nevěděl, co které tlačítko se souborem provede. 64

Pomocí použití tlačítek Choose File a Upload může uživatel na server nahrát nový soubor. Tlačítko Choose File otevře dialogové okno, které umožňuje procházet lokální disk uživatele a vybrat na něm požadovaný soubor. Tlačítko Upload slouží ke spuštění nahrávaní na server. Pomocí tlačítka New Folder uživatel vytvoří novou složku ve své adresářové struktuře. Poslední dvě tlačítka slouží ke změně zobrazení položek v pravém sloupci. Pro vrácení se do základní složky adresářové struktury musí uživatel vybrat nějaký soubor v základní složce složce a poté změnit zobrazení pomocí tlačítek v pravém horním rohu. Použití správce souborů se nevztahuje pouze na vkládání obrázku do stránky. Stejným způsobem může uživatel vybírat i soubory, na které se chce ze stránek odkazovat. 6.3.6 Události Odkaz Události vede na stránkovaný seznam všech událostí. Procházení jednotlivých stránek funguje stejně jako u aktualit, viz předcházející kapitola. I u událostí jsou uživateli, který nemá potřebná oprávnění, zobrazeny pouze ty záznamy, které vytvořil. K vytváření a upravování událostí má uživatel k dispozici formulář, který umožňuje zadání názvu, popis, datum začátku a konce události a výběr aktuality, k níž se daná událost váže. K výběru příslušných dat může uživatel použít vyskakovacího kalendáře. Události lze ve veřejné části aplikace procházet pomocí kalendáře v pravém sloupci. Datumy, které obsahují alespoň jednu událost, jsou zvýrazněny červeným pozadím. Po kliknutí na takto zvýrazněné datum se uživateli otevře dialogové okno se seznamem všech událostí, které se konají v daný den. Pokud tyto události obsahují vazbu na aktuality, je u nich uveden odkaz na danou aktualitu. Zároveň stránka s odpovídající aktualitou obsahuje informace o všech událostech, které se k ní váží. 6.3.7 Kategorie stránek Kategorie stránek reprezentují odkazy první úrovně ve veřejné části aplikace. Jelikož veřejná část aplikace obsahuje 4 různá menu, je u kategorií stránek kromě názvu dané kategorie potřeba zvolit i menu, v kterém se má zobrazit. Obrázek 37: Přehled všech uložených kategorií stránek Vytváření, upravování a mazání funguje i u kategorií stránek dříve popisovaným způsobem. Odkaz Přehled, viz předchozí obrázek, vede na seznam všech stránek dané kategorie. 65

6.3.8 Stránky V případě, že se dostane uživatel na seznam stránek pomocí odkazu z levého menu, zobrazí se mu všechny stránky. Ale u každého záznamu bude mít pouze možnost jeho editace. Pokud chce přidat stránku, nebo naopak nějakou smazat, musí se na tento seznam dostat přes odkaz Přehled u kategorií stránek. Ty byly popsány v předešlé kapitole. Pro vytváření a editaci stránky má uživatel k dispozici formulář s integrovaným textovým editorem a správcem souborů. S textovým editorem a správcem souborů se pracuje stejně jako v případě aktualit, které byly popsány v kapitole 6.3.5. Každá stránka patří do jedné kategorie stránek. Pod touto kategorií stránek je poté ve veřejné části aplikace dostupný odkaz na tuto stránku. 6.3.9 Vzdělávací programy Odkaz Vzdělávací programy vede na seznam vzdělávacích programů. Ty slouží k filtrování vzdělávacích materiálů. Záznam reprezentující vzdělávací program je tvořen pouze názvem daného programu. Ke správě vzdělávacích materiálů má uživatel k dispozici odkazy vedoucí na stránky pro vytvoření nového a úpravu stávajícího vzdělávacího materiálu. Mazání probíhá opět pomocí dialogového okna popsaného v kapitole 6.3.1. 6.3.10 Předmětová odvětví Předmětová odvětví slouží stejně jako vzdělávací programy k filtrování vzdělávacích materiálů. Každé odvětví je reprezentováno jeho názvem a předmětem, do kterého spadá. Například na následujícím obrázku je algebra předmětovým odvětvím matematiky. Obrázek 38: Přehled všech předmětových odvětví 6.3.11 Vzdělávací materiály Odkaz Vzdělávací materiály vede na správu úložiště vzdělávacích materiálů. Pro možnost jejich správy je třeba nejdříve vybrat předmět. Po provedení výběru může uživatel na server nahrávat nové materiály, upravovat dodatečné informace u materiálů a mazat již nahrané materiály. Uživatel, který nemá veškerá oprávnění ke vzdělávacím materiálům, může spravovat materiály jen těch předmětu, pro které má potřebné aprobace. Zároveň může spravovat jen ty materiály, kterých je autorem. Při vytvoření nového materiálu musí uživatel uvést kromě názvu a popisu i do jakého vzdělávacího programu a odvětví materiál patří. Dále musí určit pro 66