four .net web frameworks in less than an hour
DESCRIPTION
In the .NET space the overwhelming majority of web projects are built with ASP.NET in one form or another.But there are alternatives. Alternatives that offer other approaches, and supports other ways of thinking.Alternatives that are open source. Altenratives that run on Mono.Maybe one of those alternatives is the better fit for your next project - except if you don't know about them you will never know. In this code heavy talk I'll show the same sample application in the four Open Source .NET web frameworks FubuMVC, OpenRasta, Nancy and Frank.You will not become an expert at anything by attending this talk - but you may discover just the right web framework for your next project.TRANSCRIPT
Four Other .NET Web Frameworks in Less Than an Hour
Christian Horsdal@chr_horsdal
http://horsdal.blogspot.com/
3
Lead Software Architect @ Mjølner Informatics Husband and Father Some who enjoys
Clean code TDD’ing When ’GF wins Simplicity Whisky
Who Am I?
4
There are alternatives to ASP.NET Know them!
Style matters
Tradeoffs, tradeoffs, tradeoffs Conventions <-> explicitness DRY <-> separation of concerns Abstract <-> concrete
Why?
5
Run anywhere
IoC/DI to the bone
Embrace HTTP
OSS and community driven
Why?
6
A taste of some alternatives
FubuMVC
OpenRasta
Nancy
Frank
What will you learn?
7
Sample
8
One Model In One Model Out Aka OMIOMO Aka Russian Doll
Convention over Configuration
Really cool built-in diagnostics
Everything is POCOs
FubuMVC – At a glance
9
GET “/”
• No params
HomeController.get_Home
• Returns HomeViewModel
HomeView.cshtml
• Takes HomeViewModel
FubuMVC – ShortUrl Overview
POST “/”
• UrlShorteningModel
HomeController.post_Home
• Takes UrlShorteningModel
• Returns UrlShorteningViewModel
UrlShortenedView.cshtml• Takes
UrlShorteningViewModel
GET “/42”
• ShortenedUrlModel
HomeController.post_Home
• Takes ShortenedUrlMode• Returns FubuContinuation
10
FubuMVC – ShortUrl – Serving the FORM
public class HomeController{ public HomeController(UrlStore urlStore) { this.urlStore = urlStore; }
public HomeViewModel get_home() { return new HomeViewModel(); } …}
public class HomeViewModel { }
@model ShortUrlInFubuMvc.HomeViewModel@{ Layout = null;} <!DOCTYPE html><html> <body> <form method="post" action="home"> <label>Url: </label> <input type="text" name="url"/> <input type="submit" value="shorten"/> </form> </body></html>
11
FubuMVC – ShortUrl – POST the FORM
public UrlShorteningViewModel post_home(UrlShorteningModel input) { var shortenedUrl = input.Url.GetHashCode().ToString(); urlStore.SaveUrl(input.Url, shortenedUrl);
return new UrlShorteningViewModel { Host = "localhost:51862", HashCode = shortenedUrl }; }
public class UrlShorteningModel { public string Url { get; set; } }
public class UrlShorteningViewModel{ public string Host { get; set; } public string HashCode { get; set; }}
12
FubuMVC – ShortUrl - Redirecting
public FubuContinuation get_Url(ShortenedUrlModel input) { var longUrl = urlStore.GetUrlFor(input.Url) ?? "/notfound/"; return FubuContinuation.RedirectTo(longUrl); }
public class ShortenedUrlModel { public string Url { get; set; } }
13
Three things: Resources Handlers Codecs
Automatic conneg
Everything is POCOs
OpenRasta– At a glance
14
Resource: “/” “/{shortenedUrl}” Home
Handler HomeHandler
“Codecs” WebForms viewengine Form data
Home resourceHomeHandler
GET “/” POST “/” GET “/42”
OpenRasta – Shorturl Overview
15
OpenRasta– ShortUrl – Serving the FORM
public class HomeHandler { public HomeHandler(IRequest request, UrlStore urlStore) { this.request = request; this.urlStore = urlStore; }
public Home Get() { return new Home(); } …}
public class Home{ public string LongUrl { get; set; } public string ShortUrl { get; set; } public string Host { get; set; }}
public class Configuration : IConfigurationSource { public void Configure() { using (OpenRastaConfiguration.Manual) { ResourceSpace.Has .ResourcesOfType<Home>() .AtUri("/").And.AtUri("/home") .And.AtUri("/{shortenedUrl}") .HandledBy<HomeHandler>() .RenderedByAspx("~/Views/Home.aspx");
ResourceSpace.Uses .Resolver.AddDependencyInstance<UrlStore>(new MongoUrlStore("mongodb://localhost:27010/short_url")); } } }
16
OpenRasta– ShortUrl – POST the FORM
public Home Post(Home input) { input.ShortUrl = input.LongUrl.GetHashCode().ToString(); input.Host = request.Uri.Host + ":" + request.Uri.Port;
urlStore.SaveUrl(input.LongUrl, input.ShortUrl);
return input; }
17
OpenRasta– ShortUrl - Redirecting
public OperationResult Get(string shortenedUrl) { var longUrl = urlStore.GetUrlFor(shortenedUrl); if (longUrl != null) return new OperationResult.SeeOther { RedirectLocation = new Uri(longUrl) }; else return new OperationResult.NotFound(); }
18
Lightweight, low ceremony Just works But easily swappable
DSLs
Built in diagnostics
Testability is first class
Nancy– At a glance
19
Modules ShortUrlModule
Routes Get[“/”] Post[“/”] Get[“/{shortenedUrl}”]
A lambda for each
HTTP request Routes Handler
functionRespons
e
Nancy – Shorturl Overview
20
Nancy– ShortUrl – Serving the FORM
public class ShortUrlModule : NancyModule{ public ShortUrlModule(UrlStore urlStore) { Get["/"] = _ => View["index.html"]; … } …}
<!DOCTYPE html><html> <body> <form method="post" action="home"> <label>Url: </label> <input type="text" name="url"/> <input type="submit" value="shorten"/> </form> </body></html>
21
Nancy– ShortUrl – POST the FORM
public class ShortUrlModule : NancyModule{ public ShortUrlModule(UrlStore urlStore) { Get["/"] = _ => View["index.html"]; Post["/"] = _ => ShortenUrl(urlStore); … } private Response ShortenUrl(UrlStore urlStore) { string longUrl = Request.Form.url; var shortUrl = longUrl.GetHashCode().ToString(); urlStore.SaveUrl(longUrl, shortUrl); return View["shortened_url", new { Request.Headers.Host, ShortUrl = shortUrl }]; } …}
22
Nancy– ShortUrl - Redirecting
public class ShortUrlModule : NancyModule{ public ShortUrlModule(UrlStore urlStore) { Get["/"] = _ => View["index.html"]; Post["/"] = _ => ShortenUrl(urlStore); Get["/{shorturl}"] = param => { string shortUrl = param.shorturl; return Response.AsRedirect(urlStore.GetUrlFor(shortUrl.ToString())); }; }…}
23
F#
Bare bones approach to HTTP services
Leverage WebAPI
Compositional
Frank– At a glance
24
Frank– ShortUrl – Serving the FORM
let urlShortenerView = @"<!doctype html><meta charset=utf-8> <title>Hello</title> <p>Hello, world! <form action=""/"" method=""post"" enctype=""multipart/form-data""> <input type=""input"" name=""longUrl"" value=""long url""> <input type=""submit"">"
let urlShortenerForm request = async { return respond HttpStatusCode.OK (new StringContent(urlShortenerView, System.Text.Encoding.UTF8, "text/html")) <| ``Content-Type`` "text/html"}
25
Frank– ShortUrl – POST the FORM
let createShortUrl (request: HttpRequestMessage) = async { let! value = request.Content.AsyncReadAsMultipart() let longUrl = value.FirstDispositionNameOrDefault("longUrl") .ReadAsStringAsync().Result; let urlKey = longUrl.GetHashCode().ToString()
urlStore.Add(urlKey, longUrl) let shortUrl = baseUri + "/" + longUrl.GetHashCode().ToString() return respond HttpStatusCode.OK (new StringContent(shortUrlCreatedView(shortUrl), System.Text.Encoding.UTF8, "text/html")) <| ``Content-Type`` "text/html"}
26
Frank– ShortUrl - Redirecting
let getShortUrl (request: HttpRequestMessage) = async { let urlKey = request .RequestUri .Segments.[request.RequestUri.Segments.Length - 1] let longUrl = urlStore.[urlKey] return respond HttpStatusCode.Redirect (new EmptyContent()) <| Location (new Uri(longUrl))}
let rootResource = routeResource "/" [ get urlShortenerForm <|> post createShortUrl ]let redirectReource = routeResource "/{shortUrl}" [ get getShortUrl ]
let app = merge [ rootResource; redirectReource ]
let config = new HttpSelfHostConfiguration(baseUri)config.Register app
27
Why, again?
There are alternatives to ASP.NET Know them!
Style matters
Tradeoffs, tradeoffs, tradeoffs
28
FubuMVC OMIOMU
OpenRasta Resources, Handlers, Codecs
Nancy DSL
Frank F#
What might you have learned?
A taste of some altenatives
WHEN, WHAT, WHERE?FubuMVC, OpenRasta, Nancy, Frank
29
Evaluation page: http://bit.ly/cd2012b2Please fill in! ‘kthxbai