Når jeg tænker på Single Page Architecture (SPA) er der en række problemer som popper op, som f.eks: Back button virker ikke, da browseren ikke oplever det som side skift når man navigere rundt på siden, eller at UX delen er en suppe af div-tags of javascript, som hurtig bliver svær at overskue og umulig at debugge.
Derfor er jeg lidt skeptisk når jeg høre om det nye sort hos ASP.NET nemlig SPA – single page architecture, som skulle være en nem og overskuelig måde at lave apps på, netop ved at man kun har en HTML side hvor alt logic bliver lavet i siden med Javascript, for mig lyder det som gammel vin på nye flasker. Men man skal jo aldrig sige aldrig, så derfor tror jeg også det ville være spændende at komme med til training sessionen Build a SPA in Just One Day på GOTO konferencen i Aarhus.
Men mens man venter er der mange tutorials på nettet, som man kan kigge på. Men hvorfor ikke skrive en selv 🙂
Jeg hellere indrømme at jeg har startet den her blog post to gange; Første jeg prøvede var lave en ny løsning i VS2013, med en SPA template. Men SPA templaten inkludere MVC, hvilket jo er et godt framework, men en hel del mere end hvad jeg er ude efter. Men lad os lige tage to skridt tilbage først.
Mit projekt (for man er vel ikke udvikler, hvis man ikke har en lille projekt ide) er at lave en side hvor jeg kan lister de bøger som jeg har stående der hjemme, lave ratings på dem jeg har læst også få anbefalinger til hvilke jeg skal læse næste gang. Det kan så udvides til at venner kan tilføje deres bøger, vi kan bruge hinandens anmeldelser til at lave bedre anbefalinger. Så kommer deres venner på besøg, og vil også være med. Derefter går det hurtigt med verdens herredømmet og vi ender med enten at købe Facebook, eller blive opkøbt af Amazon.
Ikke? man kan jo altid drømme.
Men fra et mere teknisk synspunkt, så vil jeg gerne have en simpel side hvor jeg kan teste forskellige anbefalings algoritmer, og samtidig prøve at lege med forskellige nye teknologier, f.eks. MongoDb, ASP.NET SPA, OData, knockout.js, Måske SignalR, men jeg ved ikke helt om det passer ind endnu.
Før jeg overhovedet begynder at kode startede jeg med hentet data om bøger hos goodreads.com, hvor jeg har en konto med lidt over 100 bøger, og dem kan man eksporterer til en CSV fil, hvilket jo gør det til en leg at importere i mongoDb.
Så er det bare med at komme igang! En definition af SPA er ifølge wikipedia kan SPA defineres som:
In a SPA, either all necessary code – HTML, JavaScript, and CSS – is retrieved with a single page load, or the appropriate resources are dynamically loaded and added to the page as necessary, usually in response to user actions.
Det oversætter jeg til at en SPA handler om at der kun fortages et request til serveren for at hente selve “siden” og så bliver alt data opdatering håndteret ved hjælp af AJAX-kald til serveren, uden “siden” bliver loaded igen.
Med det i tankerne blev jeg noget overrasket ovet at SPA templaten i Visual Studio 2013 inkludere MVC. Nu skal man ikke kimse af MVC for det er jo et godt framework, som jeg selv har lavet flere hello-worlds i, men hvis man kigger på definitionen af SPA så passer det jo ikke helt sammen. VS2013 templaten bruger følgende arkitektur:
Jeg har så senere fundet ud af at ideen er at man laver en MVC løsning, og så lader man de sider som bygges på MVCvis hente data med AJAX, men det er jo ikke single page, men few page architecture (FPA), jeg ikke syntes passer helt overens med definitionen af SPA.
Så efter at have slåset en del med MVC og ikke kunne få det presset ned i den simple model, startede jeg forfra og brugte empty site som template med Web-API inkluderet. Da det passer bedre med mit verdensbillede (og i håbet om at jeg ikke kommer til at savne MVC, efterhånden som millioner af bruger begynder at bruge sitet).
Da jeg godt kan lide at se noget som kører i en fart, og så tilføje funktionalitet ovenpå, starter jeg med en meget simple data struktur, som jeg ligger i en folder jeg kalder Model:
namespace Books.Models
{
public class Book
{
[Key]
public Guid Id { get; set; }
public int BookId { get; set; }
public string Title { get; set; }
public string Author { get; set; }
public int MyRating { get; set; }
}
}
Det skal helt sikkert udvides senere, men det er rigeligt til at starte med. Når man har en klasse kan man autogenere en controller for klassen som håndtere hent, gem, editering og slet (så kaldte CRUD functioner.). Jeg kan godt lide OData så jeg laver en odata enabled controller. Det gøres ved at vælge Add-Controller i højreklik på controller folderen.
Det var næsten alt hvad vi skal bruge fra backend til at starte på front end, man skal lige læse den autogenerede kommentar som der er i Controlleren som siger at du skal kopiere nogle liner kode ind i WebApiConfig.cs filen, for ellers virker OData kontrollen nemlig ikke.
Og til sidst, skal vi hacke løsningen lidt fordi jeg vil gerne have EF ud af systemet og hardcode nogle bøger som vi kan arbejde med til at få det hele op og køre. I bookContext laver jeg følgende:
public class BooksContext : DbContext
{
public BooksContext() : base("name=BooksContext")
{
Books = new List();
Books.Add(new Book { Author = "Douglas Adams", BookId = 42, Id = Guid.NewGuid(), MyRating = 100, Title = "Hitchhikers Guide to the Galaxy" });
Books.Add(new Book { Author = "Umberto Eco", BookId = 2, Id = Guid.NewGuid(), MyRating = 0, Title = "L'isola del giorno prima" });
}
public List Books { get; set; }
}
Også gik jeg gennem BookController og ændrede alle metoder så det id man finder bøger på er BookId som er en int og ikke en Guid. Det betyder at man lave følgende kald, i browseren når man kører projektet:
http://localhost:51253/odata/Book(2)
Som returnere:
{
odata.metadata: "http://localhost:51253/odata/$metadata#Book/@Element",
Id: "06c89b4d-7941-4a5c-884b-c28fc87a3ab9",
BookId: 2,
Title: "L'isola del giorno prima",
Author: "Umberto Eco",
MyRating: 0
}
Hvilket er nok til at vi nu kan vende os mod frontend og dermed html og Javascript. Hvordan man bruger de data som jeg har hentet fra GoodReads er en historie for sig, som kommer i en fremtidig blog.
HTML5 og javascript, det er ikke min stærke side, så jeg vil sætte pris på alle kommentar og vittigheder omkring min kode :). Så find den røde pen frem og glæd jer til part 2.
Det problem du nævner med back-button løser HTML5 pushState 🙂
Ja, det læste jeg på wikipedia, men tænkte at de passede bedre ind i næste post om frontend :).
[…] lyder rigtigt smart, og som et spændende sted at prøve kræfter med mit bog anmeldelse site (link), når jeg har fået de første 200.000 brugere […]