Qui

Waar ben ik? Ja, ik weet het wel maar veel andere tegenwoordig niet meer. Met de verhuizing naar de nieuwe locatie voor het instituut CMI moeten wij, de docenten en studenten, opeens in twee verschillende gebouwen zijn. Nu zijn deze gebouwen maar 50 m van elkaar verwijderd, maar dit is net te onpraktisch om steeds heen en weer te lopen van kantoor naar leslokaal en weer terug. Mijn vaste kantoor is ineens niet meer zo vast voor mij.

Voor deze post wil ik gebruik maken van een nieuw systeem waarin ik kan aangeven waar ik ben. Hierbij wil ik ingaan op MVC 4, de database, beveiliging en het maken van de website voor het beheer.

Waarom de naam Qui? Qui betekend hier in het Italiaans, en dat is precies de kern van het systeem. Het gaat aangeven waar ik ben, namelijk hier. Overigens ben ik altijd hier vanuit mijn perspectief, maar dat is misschien voor een andere blogpost.

Wat zijn de onderwerpen dit keer?

  • De requirements van Qui
  • Opzetten van de omgeving (Appharbor, Bitbucket)
  • De Database
  • Opzetten van een MVC 4 website
  • Koppelen van de database met de website
  • Aanmaken van de pagina’s om de data te benaderen en te beheren
  • Beveiligen van de website

Wat kan Qui?

De kern van het systeem wordt het aangeven van de huidige locatie van een docent. Heel simpel dus. De volgende onderdelen wil ik erin hebben.

  • Als student of docent moet ik de huidige locatie van de docent kunnen vinden als deze ingevoerd is om te weten waar de docent is.
  • Als student of docent moet ik kunnen zoeken op docent om zijn gegevens op te kunnen vragen.
  • Als student of docent moet ik de huidige contact informatie kunnen opvragen op het moment dat het niet bekend is waar de docent zich bevindt om toch contact te kunnen leggen.
  • Als docent moet ik mijn huidige locatie door kunnen geven, zodat deze opgevraagd kan worden.
  • Als docent moet ik mijn gegevens kunnen aanpassen.
  • Als docent moet ik mijn huidige locatie gegevens kunnen aanpassen, zodat ik de informatie up to date kan houden.

Het systeem is dus vrij simpel en recht toe recht aan. Ideaal om er gelijk ook een blogpost van te maken ;).

In de wolken

Allereerst begin ik met het opzetten van mijn omgeving. Ik kies dit keer niet voor een HR-eigen server. Door wat slechtere ervaringen en het nog niet beschikbaar zijn van een nieuw, beter systeem, ga ik voor wat meer zekerheid. Ik gooi de meuk gelijk maar in de cloud. Hiervoor gebruik ik mijn favoriete clouddiensten Bitbucket (voor de code) en AppHarbor voor het hosten van de oplossing. Wil je weten hoe je deze het beste kan aanmaken en koppelen, check deze post even.

Nadat ik een AppHarbor applicatie en een Bitbucket repository heb aangemaakt, deze twee gekoppeld heb en een lokale folder heb geclonet met de Bitbucket repository kan ik mijn Visual Studio Solution daarin opslaan. Ik heb de MVC 4 SDK geïnstalleerd, zodat ik ook daadwerkelijk ASP.NET MVC 4 oplossingen kan maken in Visual Studio.

In mijn AppHarbor voeg ik ook gelijk een nieuwe addon toe, namelijk een Microsoft SQL Server. Ik kan nu makkelijk vanuit mijn Visual Studio (of SQL Server Management Studio) een connectie maken met de database en deze structureren.

Tabellen en relaties

Ik vind het zelf altijd makkelijker om vanuit een database model te denken dan andersom. Een datamodel geeft mij een houvast en een structuur. Ik maak dan ook eerst mijn database diagram aan in Visual Studio en hierdoor worden gelijk de tabellen aangemaakt en de relaties gelegd onderling.

In Visual Studio maak ik eerst een database connectie aan door Tools > Connect To Database te kiezen. Deze verschijnt dan in de Server Explorer als deze succesvol is aangemaakt. Voor de inloggegevens kopieer ik die van AppHarbor (SQL Server > Go to SQL Server). Ik hernoem deze dan ook wel even in de Server Explorer, zodat deze een duidelijkere aanduiding heeft.

Als ik mijn nieuw aangemaakte database connectie openklap in de Server Explorer kan ik ook Database Diagrams openen. Hij geeft dan een melding dat er objecten moeten worden aangemaakt en dat is OK. Ik kies Add New Diagram uit het context menu en krijg een nieuw scherm voor me. Er zijn nog geen tabellen dus ik sluit het venster.

In het lege witte veld gebruik ik het context menu om een nieuwe tabel aan te maken. Ik maak dan de onderstaande tabellen aan.

Een korte toelichting op het diagram. Een docent kan meerdere soorten contact mogelijkheden hebben. Ook kan een docent inchecken op meerder locaties waarbij elke keer een nieuwe date-time wordt gezet. De laatste is uiteraard de meest recente.

Online

De volgende stap is het opzetten en beginnen van een nieuwe Solution in Visual Studio en het aanmaken van een MVC 4 project. Ik maak de Solution aan in de folder die ik heb geclonet en het is van het type MVC 4. Ik kies dan een Internet Application met de Razor View Engine. Dit biedt mij voldoende mogelijkheden out-of-the-box om mijn oplossing aan te passen naar mijn wensen.

Nadat mijn Solution is aangemaakt voeg ik deze toe aan de Source Control voordat ik het vergeet. Eventueel kan je Commit kiezen en Synchronize om de website online te publishen. Gewoon F5 werkt ook om het lokaal te testen.

Een korte toelichting op wat er allemaal is aangemaakt. Allereerst is het belangrijk te weten wat MVC inhoudt. MVC staat voor Model View Controller. Dit zijn de drie lagen die gebruikt worden waarbij de Model een data representatie is, de View een pagina of het gene wat de gebruiker ziet en de Controller de tussenlaag die zorgt voor de intelligentie. Voor meer informatie kan je hier kijken.

Waar is de data?

Vervolgens ga ik mijn database koppelen aan de nieuwe website. Dit doe ik door middel van het Entity Framework. Deze ga ik gebruiken als een Model binnen mijn Solution. Ik maak eerst een nieuwe folder DataModels aan. Hierin ga ik de nieuwe representaties van de database tabellen zetten. Dit doe ik in de vorm van het Entity Framework die veel werk voor mij uit handen neemt.

In de folder maak ik een nieuw item aan Add > New Item. Ik kan onder de categorie Data het ADO.NET Entity Data Model kiezen. Deze noem ik DataModel.edmx. Hij zal dan gelijk een wizard opstarten om de entiteiten aan te maken. We hebben al een database, dus ik kies Generate From Database. Het makkelijke nu is, omdat ik al een connectie aangemaakt heb, ik deze gelijk kan kiezen in de lijst met connecties. Anders moet ik een nieuwe maken en de gegevens van AppHarbor gebruiken. Ik sla in dit geval ook het password op en noem de referentie naar de totale connectionstring DataEntities. Dit wordt zo opgeslagen in de Web.config, het configuratie bestand van de website.

Vervolgens selecteer ik mijn tabellen die ik nodig heb. Ik selecteer eigenlijk gewoon alles, behalve de sysdiagrams. Die laatste tabel is een tabel voor SQL Server zelf om de data van de diagrammen in op te slaan. Een system table dus en die heb ik niet nodig nu. Ik geef mijn Model Namespace de naam DataModel.

Het Entity Framework zal nu de database doorlopen en de tabellen omzetten in classes (entiteiten) die we dadelijk makkelijk vanuit de code en vanuit het MVC framework kunnen aanroepen en gebruiken. Ik wijzig niets en sluit het bestand. Voordat ik verder ga run ik even een Rebuild. Dit doe ik om te zorgen dat alle referenties naar het nieuwe data model goed staan. Vergeet je dit, dan kan je het nog niet gelijk kiezen bij het maken van nieuwe controllers.

Mijn Solution inhoud ziet er nu uit zoals de bovenstaande afbeelding. Ik kan nu ook eventueel het nieuwe datamodel commiten en publishen.

Controlling the flow

Tijd om de pagina’s aan te maken. Zoals ik al eerder heb aangekaart worden de pagina’s Views genoemd. Deze worden bestuurd door de Controller en gevuld door de Model. We kunnen binnen dit MVC project een nieuwe controller aanmaken. Visual Studio zal dan voor ons gelijk een Model en een View aanmaken als wij een nieuwe Controller maken. Dat scheelt :).

In de folder Controllers doe ik Add > Controller. Let op dat je al ge-Rebuild hebt, anders kan je de juiste referenties naar de Entity Framework modellen niet vinden. Ik begin met de entiteit Lecturers.

Ik kies eerst de Data context class. Dit is namelijk de context waaruit hij daarna de entiteiten gaat zoeken. Dit is de naam van het datamodel die we hebben aangemaakt. Daarna kies ik de class zelf, in dit geval de Lecturers class (entiteit). Ook selecteer ik dat ik de read en write acties wil gaan gebruiken. Dit houdt in dat ik een overzicht krijg met de data, de mogelijkheid heb om nieuwe data toe te voegen, te wijzigen en te verwijderen.

Ik zie dat er een nieuwe controller is aangemaakt en een folder binnen de Views met de naam Lecturer met daarin alle verschillende CRUD (create, read, update, delete) functionaliteiten. De controller is op dit moment open en daarin zijn de verschillende methodes te zien die aangeroepen kunnen worden.

Om de nieuwe functionaliteit te kunnen benaderen moet het nog toegevoegd worden aan het menu. Hiervoor ga ik naar de Shared folder binnen de Views. Hier staat een bestand _Layout.cshtml en die open ik. Hier is het menu te vinden en daarin kunnen we de nieuwe referenties toevoegen.

<nav>
	<ul id="menu">
		<li>@Html.ActionLink("Home", "Index", "Home")</li>
		<li>@Html.ActionLink("Lecturers", "Index", "Lecturer")</li>
		<li>@Html.ActionLink("About", "About", "Home")</li>
		<li>@Html.ActionLink("Contact", "Contact", "Home")</li>
	</ul>
</nav>

Op regel 4 heb ik de nieuwe referentie toegevoegd. Hierin kan heb ik de volgende waardes gebruikt: “Lecturers” is de naam die ik in mijn menu wil zien. Daarna gebruik ik Index wat de naam is van de methode in de Controller. De laatste waarde is de context waar de Index zich in bevindt. In dit geval “Lecturer” want dat is de context waarbinnen de views zijn aangemaakt.

De website zit er nu als volgt uit.

Als ik op Lecturers klik, dan krijg ik de index pagina van Lecturers. Hier kan ik nieuwe data aanmaken. Dat geeft mij de invoervelden en bij het opslaan wordt het direct in de database opgeslagen.

Dit zelfde riedeltje kan ik herhalen natuurlijk voor de andere tabellen (niet de koppeltabellen). Mijn menu wordt wel erg groot dan, maar goed, dat is een probleem voor dan.

Wie ben je?

Natuurlijk moet niet iedereen onbeperkte toegang hebben tot dit systeem. Dit kunnen we afvangen met rollen, rechten en gebruikers. Een gebruiker kan inloggen, wordt gekoppeld aan een rol en een rol heeft rechten.

Wat ik wil gebruiken hier is het ingebouwde mechanisme van inloggen en beheren van rechten van de website. ASP.NET biedt dit namelijk al aan en heet Forms Authentication. Binnen MVC 4 gaat dit heel makkelijk. Het framework maakt namelijk al zelf de tabellen aan als je voor het eerst in het registratie gedeelte komt. Wel moet je zorgen dat de connectionstring naar de database verwijst in de web.config.

Hiervoor heb ik het configuratie bestand nodig van de ASP.NET website, de web.config in de root van de Solution. Als ik deze open zie ik bij connectionstrings onder andere de tag DefaultConnection staan. Deze connectionstring moet je vervangen met die van AppHarbor.

Toegang

Het laatste wat ik moet doen is het afvangen van de permissies per rol. Bijvoorbeeld, alleen een Lecturer mag een nieuwe locatie aanmaken. Ik heb daarvoor een nieuwe Controller gemaakt voor SubLocations. Binnen de SubLocationController.cs kan ik dan de create-methode aanpassen en zorgen dat alleen members van de Lecturer rol deze mogen aanroepen.

[Authorize(Roles="Lecturer")]
public ActionResult Create()
{
	ViewBag.MainLocation = new SelectList(db.MainLocations, "Id", "Name");
	return View();
}

Hier heb ik op regel 1 de Authorize tag geplaatst boven de methode om dit af te vangen. Vergeet het ook niet bij de public ActionResult Create(SubLocations sublocations) ook te gebruiken.

Conclusie

Het opzetten van een nieuwe interface voor je online database kan heel snel gaan met ASP.NET MVC 4. Het belangrijkst is dat je datamodel goed in elkaar zit, zodat het MVC Framework dit kan gebruiken om de juiste schermen en Controller methodes voor aan te maken.

Er zijn meerdere vormen van Authenticaties mogelijk, nu heb ik de ingebouwde Forms Authentication gebruikt, maar dit kan natuurlijk verder worden uitgebreid. Mocht je de huidig ingelogde gebuiker willen weten dan kan je dat doen met de code:

HttpContext.User.Identity.Name;

Succes!

PS: NuGet Package Restore

Ik kwam erachter dat de Solution zoals die nu is niet helemaal lekker werkt op AppHarbor. Ik kreeg namelijk een error dat hij bepaalde references naar het EntityFramework niet kan vinden tijdens de build. Dit blijkt een probleem te zijn met de package van het EntityFramework. Als we namelijk MVC 4 gebruiken dan hebben we ook een nieuwe versie van het EF. Bij MVC 3 is dat nog niet het geval en dan krijg je deze error niet.

Wat moet je doen? We gaan zorgen dat de package van het EF niet automatisch wordt verzonden naar AppHarbor. Daarvoor heeft NuGet (de bron van waar de package vandaan komt) een hele mooie optie, namelijk NuGet Package Restore. Om deze optie aan te zetten kan heel simpel, binnen het contextmenu van de Solution de optie Enable NuGet Package Restore worden gekozen.

Je krijgt dat eerst een alert met wat er allemaal gaat veranderen. Kies Yes en dan worden de benodigde wijzigingen doorgevoerd.

Nadat de optie aanstaat wordt een nieuwe map toegevoegd aan de Solution genaamd .NuGet. Hierin staan de nieuwe bestanden en referenties die nodig zijn.

Nu kan de nieuwe Solution worden gecommit en gepublisht naar AppHarbor.

Toch niet?

Mocht je de hele package restore willen verwijderen, dan heeft dat wat haken en ogen. Sluit je Solution en open het .csproj bestand in NotePad++ bijvoorbeeld. Zoek de volgende twee regels en verwijder die.

<RestorePackages>true</RestorePackages>
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />

Verwijder ook de .NuGet folder en open dan de Solution weer. Het sluiten van de Solution is wel belangrijk voordat je de regels verwijderd, anders zal Visual Studio de wijzigingen cachen en opnieuw toevoegen als je het project opnieuw laadt.

Ik heb dit er even bijgezet voor die gene die toch de optie niet aan willen hebben. Voor ons is dat wel van belang, dus laat hem aan staan en publish naar AppHarbor :).

  6 comments for “Qui

  1. 12 oktober 2012 at 13:03

    Zeer leuke post Bob! Cool uitgelegd ook.

    Ben alleen verbaasd dat jij het niet in de Azure Cloud host ;) ?

    • Bob
      13 oktober 2012 at 21:17

      AppHarbor is gratis? :)

  2. 12 oktober 2012 at 14:29

    Heel informatieve post Bob! Ik word er altijd blij van om te zien dat er ook nog docenten zijn die actief bezig zijn met development :)

    Wel even een discussiepunt: je geeft aan dat het voor jou het makkelijkst is om vanuit een Database Model te denken. Met het gebruik van EntityFramework is dat ook de makkelijkste (enige?) manier. Toch vraag ik me af of het niet betere applicaties oplevert, als je denkt vanuit je domein-model en het ontwerpen van een applicatie doet vanuit het bedenken van de juiste classes. Eigenlijk volgens goed “OOP” fatsoen ;)

    Dit heeft voor persistence grote gevolgen: je schrijft normale C# objecten met de juiste business logic, en voegt later een ORM layer toe. Hiermee vermijdt je een beetje het inherente verschil tussen classes die samenwerken en tables met relations. De Object Relational Impedance Mismatch.

    Ik heb zelf in mijn PHP tijd veel met Doctrine 1.2 gewerkt, en die forceert je – net als bv. het ORM in Ruby on Rails trouwens – om de classes die je wil persisten te extenden vanuit een standaard base class. ActiveRecord pattern zeg maar. Toen ik op een later moment in Java met Hibernate werkte, ging er een wereld voor me open omdat je nu gewoon als programmeur kunt denken en je niet vooraf al bezig hoeft te houden met het datamodel.
    Hoe kijk jij tegen die verschillende invalshoeken aan? Wel eens NHibernate gebruikt?

    Interessant om te lezen ook over deze “Object Relational Impedance Mismatch”: http://www.codinghorror.com/blog/2006/06/object-relational-mapping-is-the-vietnam-of-computer-science.html (ben het overigens niet met het artikel eens dat ORMs slecht zijn)

    • Bob
      13 oktober 2012 at 22:35

      Het Entity Framework ondersteund juist al OOP. Het is een soort combinatie van beide. Het genereert de classes vanuit je datamodel (eventueel) en laat het je aanpassen om het richting OOP te brengen als je dat wilt. Je zou ook eerst je OOP classes kunnen maken en dan een Database kunnen genereren, ligt er maar net aan welke insteek je wilt hebben.

      NHibernate werkt hetzelfde voor zover ik weet. Ik heb zelf nog niet NHibernate gebruikt overigens.

  3. 12 oktober 2012 at 17:02
  4. Bob
    14 oktober 2012 at 09:57

    Ik heb de NuGet Package Restore oplossing bij de post gezet omdat het bleek dat de Solution niet goed build op AppHarbor zonder dit. Dit heeft te maken met de combinatie AppHarbor, MVC 4 en EntityFramework. Met MVC 3 is er geen probleem.

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd met *

Zoals de meeste websites gebruiken we cookies om een meer persoonlijke en snelle service te bieden.

Wij gebruiken cookies zodat onze website meer efficiënt kan functioneren, om de prestaties te verbeteren en, eventueel, om op maat reclame van onze partners aan te bieden. Als u doorgaat gaan we ervan uit dat u akkoord gaat alle cookies te krijgen van onze website.

To accept cookies please Click To Continue