In podcast 105 van Scott Hanselman (link) komt CSLA.NET voorbij. Je kunt het beste op de website van het project beginnen, daar staan links naar een "getting started" en een wiki: https://cslanet.com/. Broncode van het project staat in Github: link.
Gestart met de "getting started". In het kort komt het erop neer dat je je "business-logica" niet in je views, controller, viewmodel en presenter moet stoppen. De enige plek die dan overblijft is het model. Maar de modellen worden door veel developers als "data-containers" gebruikt. Met CSLA moet je het wel goed kunnen krijgen.
Na de uitleg komt er een verwijzing naar het gratis e-book: link. Dan heb je ook meteen een boek van 127 pagina's te pakken. Het eerste deel is uitleg over n-tiers, beveiliging en de 5-layer architectuur: Interface (dat kan HTML zijn, maar ook JSON, XML, de Razor-views), Interface Control (de code in de ViewModel-class bij een MVVM-applicatie, code in een code-behind-bestand bij webforms), Business Logic (bevat alle business-rules, data-validatie, manipulatie, bewerken van data en autorisatie), Data Access (de laag tussen de business logic en data storage waar je data kunt opvragen, bewerken, toevoegen en verwijderen (maar niet de fysieke opslag van data)), Data Storage and Management (fysiek beheer van data, via een SQL server database, een noSQL database, JSON-bestanden).
Het is een hoop theorie, tot hoofdstuk 3, pagina 55. Daar komt naast verdere uitleg ook korte codefragmenten in voor. Op pagina 81 worden de base-classes van CSLA.NET besproken. Ik had gehoopt dat het boek een soort stap-voor-stap uitleg zou geven, maar het is meer een algemeen verhaal over de verschillende lagen en hoe CSLA dat zelf implementeert. Op zich wel goed om het te lezen, want het geeft een goede uitleg over de werking en beveiliging van de applicaties die je bouwt en de lagen die daar invloed op hebben.
In het boek wordt ook al verwezen naar het feit dat het Github-project een "Samples" map heeft met voorbeelden. Ik besluit daar het MvcExample te openen om te zien wat hier nou specifiek anders aan is en wat dit framework daarmee doet.
De solution bestaat uit 3 projecten. MvcExample is een website, een .NET core 3.0 applicatie. Daarnaast heb je een BusinessLibrary-project en een DataAccess-project. Het MvcExample-project heb ik eerst bijgewerkt naar .NET core 3.1 (versie 3.0 wordt niet meer ondersteund door Microsoft).
In het MvcExample-project kun je personen beheren. Je kunt deze aanmaken, verwijderen en gegevens wijzigen (andere naam geven e.d.). In de Models-map van dit project staat alleen een ErrorViewModel om iets van een request te kunnen tonen.
De data die getoond wordt in de Views is afkomstig uit het BusinessLibrary-project. Je hebt in het Create- en Edit-scherm een model van type "PersonEdit", in het Delete- en Details-scherm heb je een model van type "PersonInfo". En in de overzichtspagina heb je een lijst van "PersonInfo"-modellen. Hiermee heb je duidelijk afgeschermd of je een read-only object hebt of een object waar je acties op uit mag/kunt voeren. Hoewel je bij een Delete-scherm misschien een PersonEdit zou verwachten, krijg je alleen read-only de eigenschappen te zien, waarbij je gaat bevestigen of de persoon echt verwijderd moet worden.
Dan gaan we naar de Controller. De code is hier beknopt, dankzij de CSLA-integratie. In de GET-acties (geef me de lijst met personen, geef me de details van één persoon) wordt gebruik gemaakt van een DataPortal-object. Met een CreateAsync of een FetchAsync geef je aan of je een bestaand object of een nieuw object terug wilt krijgen. En je geeft het type door, de PersonEdit , PersonInfo of PersonList (wat een lijst van PersonInfo-objecten is). Deze classes maak je zelf in het BusinessLibrary-project.
Die classes erven van BusinessBase, ReadOnlyBase, ReadOnlyListBase. Bij het opslaan/verwijderen van data wordt SaveObjectAsync of DeleteAsync van het DataPortal-object aangeroepen. PersonEdit die erft van BusinessBase is het interessantst, omdat je daar een BusinessRule-object hebt. Hier kun je jouw regels instellen en die valideer je vervolgens als je acties wilt uitvoeren. Dus waar je anders misschien in je eigen Save()-functie allemaal controles in je Save-functie hebt, of allemaal losse private functies die je aanroept om te valideren, heb je nu 1 object wat de validaties voor je uitvoert. Ik moet zeggen dat ik hier erg blij van wordt!
Het DataAccess-project is een class met een aantal personen wat hier in code wordt opgebouwd. Maar dat zou je natuurlijk ook kunnen koppelen met een database. In het BusinessLibrary-project zie je hoe er een [Inject]-attribuut gebruikt wordt (afkomstig uit de CSLA-nuget) om via dependency-injection het juiste object mee te geven.
De omschrijving van CSLA is misschien wat abstract, op het moment dat je de code induikt en het doorloopt zie je dat het je code een stuk "cleaner" maakt en waarschijnlijk ook een stuk minder foutgevoelig. Het zorgt ook voor de seperation of concern, die BusinessLibrary moet zorgen dat je valide data opslaat en opvraagt, waardoor jij er in jouw code geen extra acties op uit hoeft te voeren. Met ook nog eens het risico dat op een later tijdstip er een extra validatie bijkomt (ook dat veld moet verplicht zijn) en je het vergeet op 1 of 2 plekken in jouw code toe te voegen, laat de BusinessLibrary dit afhandelen.
Ik ga kijken of ik binnenkort met een project aan de slag kan gaan waar nogal wat businessrules in zitten en met dit nuget-package mijn code een boost kan geven!