360 likes | 417 Views
This article explores the current state of HTTP on .NET, highlighting issues with HttpListener and IHttpModule, and discusses future options like System.Net.Http and ASP.NET Web API. It delves into composition patterns in HTTP, components of an HTTP application, content negotiation, and problem identification. Additionally, it examines a functional programming solution to HTTP challenges using concepts like filter, map, and reduce.
E N D
Ryan Riley • Logos Bible Software • Community for F# • F# MVP • OSS: FSharpx, Fracture, Frank • @panesofglass
Outline • The State of HTTP on .NET • Composition Patterns in HTTP • Identifying Problems • Examining a Solution
Current Options • http.sys • HttpListener • IIS (IHttpModule & IHttpHandler) • Web Forms • MVC • WCF HTTP & Data Services
Future Options • System.Net.Http (BETA) • .NET 4.5 • Available on NuGet • ASP.NET Web API (BETA) • Builds on System.Net.Http • Integrated with MVC 4
OSS Options Servers FubuMVC MonoRail NancyFx OpenRasta OWIN/Gate ServiceStack.NET WebSharper … and many more! Firefly (OWIN) Fracture (F#) Kayak (OWIN) Manos de Mono Mono XSP Frameworks
Component Parts • Request/Response Lines • Methods, URIs, Status Codes • Headers • General, Request, Response, Content • Resources • Representations • Hypermedia
Simplest HTTP Application HttpRequestMessage -> HttpResponseMessage
Resources GET /item/1 + POST /item/1 + PUT /item/1 + OPTIONS /item/1 = Resource at / with GET, POST, PUT, & OPTIONS
HTTP Applications / + /items + /item/{itemId} + /help = Typical HTTP “application”
Content Negotiation Server Supports application/xml;q=0.9 application/json;q=0.8 text/plain;q=0.5 application/json text/plain text/html Client Accepts application/json
HttpListener • Low-level • Defines the signature for a single application only • HttpListenerContext provides a singleton; no chance to intercept and chain behavior • Routing requests requires custom handling; typically by using imperative if-then-else • No means of chaining or composing multiple listeners
HttpListener HttpListener.Start ("http://localhost:8082/", (fun (request, response) -> async { match request.Url.LocalPath with | "/post" -> // Send message to the chat room room.SendMessage(request.InputString) response.Reply("OK") | "/chat" -> // Get messages from the chat room (asynchronously!) let! text = room.AsyncGetContent() response.Reply(text) | s -> // Handle an ordinary file request let file = root + (if s = "/" then "chat.html" else s.ToLower()) if File.Exists(file) then let typ = contentTypes.[Path.GetExtension(file)] response.Reply(typ, File.ReadAllBytes(file)) else response.Reply(sprintf "File not found: %s" file) }), cts.Token)
IHttpModule & IHttpHandler • Low-level • HttpContext has the same problems as HttpListenerContext • IHttpHandler could represent a Resource, but method mapping is imperative • IHttpModule provides a middleware layer for routing or hosting multiple IHttpHandlers • System.Web.Routing surfaces the routing component
IHttpModule & IHttpHandler interface IHttpModule { void Dispose(); void Init(HttpApplication context); } interface IHttpHandler { bool IsReusable { get; } void ProcessRequest(HttpContext context); }
ASP.NET Web Forms • HTML composition via MasterPages, Pages, and Controls • Suffers many problems associated with IHttpModule and IHttpHandler • Evented model allows for interception • No built-in support for other representations • Pages loosely correlate to Resources • Application composition and routing by file path
ASP.NET MVC • Suffers many problems associated with IHttpModule and IHttpHandler • Primarily HTML generation but allows for better HTTP control • Built-in support for handling Ajax requests • ActionFilters allow for behavior composition at different points: Authorize, ActionExecuting, ActionExecuted, ResultExecuting, ResultExecuted
ASP.NET MVC, cont. • Content Negotiation is still very manual • ViewEngines and Serializers can be made to render various representations • ViewEngines offer representation composition • Controllers ~ Resources, but not quite • Areas and Routing allow for Nested Resources, to a degree
Problem Summary • Have: • Limited interception for cross-cutting concerns • Representation composition • Do not have: • No easy resource composition • No built-in content negotiation
Composition for Conneg • Rendering • Imperative if-then-else • Serializers • Location • Within the specific method handler (common for imperative) • Top-level (common for serializers) • Why not both?
Nested Resources • Imperative if-then-else • Routing • MVC Areas offer another level • What about more than one level? • Rails – problem with deep URIs • System.Web.Routing does everything at the top-level, so tracking deeper resource trees is difficult.
Function Composition • Functional programming offers solutions to these problems • Filter • Map • Reduce
Frank • F# DSL using System.Net.Http • Headers composition • Follows the natural composition of HTTP • Frank Resources == HTTP Resources • Define your own conventions!
Simplest HTTP Frank Application HttpRequestMessage -> HttpResponseMessage HttpRequestMessage -> Async<HttpResponseMessage>
Define a Method Handler // handler let echo request = async { let! body = request.Content.AsyncReadAsString() return HttpResponseMessage.ReplyTo(request, body) } // method handler get echo
Define a Resource let helloworld request = async { … } let echo request = async { … } let resource = route “/” (get helloworld <|> post echo)
Define an Application let todoListResource = route “/” (get todoList <|> …) let todoItemResource = route “/item/{1}” (put …) let app = merge [ todoListResource; todoItemResource]
Leverage Conneg valnegotiateMediaType = formatters -> HttpRequestMessage -> string -> Async<HttpResponseMessage> let echo = negotiateMediaType formatters <| fun request -> request.Content.AsyncReadAsString())
WebSharper • One language for both client and server • Can leverage to cleanly separate parts • Use WebSharper to generate code-on-demand to send to the client • Plays well with existing tools
Resources • ASP.NET Web Forms in F# • ASP.NET MVC in F# • Figment DSL for MVC • Frank DSL for Web API • WebSharper • Pit FW
Thank you! • Please rate this talk: http://speakerrate.com/talks/9293-the-functional-web