Middleware in the WCF Web APIs

In the last post I noted that the next post would describe middleware. For those unfamiliar with projects like WSGI and Rack, middleware is a module that wraps an application with additional functionality, such as logging, and is itself an application. Middlewares can add operations to the incoming request, the outgoing response, or wrap the entire process.

In the WCF Web APIs, the Channel model fulfills this role. Those are as yet unreleased in the current bits. However, the Processor pipeline offers another option. No, it doesn’t quite fit the definition above, but Processors allow you to add functionality to an app, providing a similar, if not the same outcome. Included in the current bits are an abstract MediaTypeProcessor, PlainTextProcessor, HtmlProcessor, XmlProcessor, and JsonProcesor. These can be hooked up through configuration to match an Accept header to perform conneg. Thus, your app can return any object, and the processor(s) will intercept and take care of serializing the outgoing response. Handy.

If you’ve been following other posts related to the WCF Web APIs, you’ll have likely come across Glenn Block’s roundup post that included Steve Michelotti’s post on rendering with the Razor view engine and Christian Weyer’s post describing how to configure JSON.NET as the default JSON serializer. Both are excellent examples of processors. With Christian’s permission, his JSON.NET processors, JsonNetProcessor and BsonSerialiser, were added to the WCF HTTP Contrib project.

I was recently wishing to use NHaml and thought about taking Steve’s excellent example as a basic framework. Then I took a look at Dotan Nahum’s Nina project and discovered something even better. Nina includes a view engine abstraction layer, similar in principle to Ryan Tomayko’s tilt library for Ruby. (You can find my initial efforts at extracting the view engine library on my fork.) Now, instead of supporting just one view engine, you can render using any of several supported view engines! Razor, Spark, NHaml, and NDjango are currently supported.

Here’s the code for the ViewEngineProcessor. You’ll notice I had to extend the MediaTypeProcessor with a generic version in order to work with the view engine api. It makes wiring things up a little messier, but nothing a clever container couldn’t handle. More work to come there.


view raw

gistfile2.txt

hosted with ❤ by GitHub


using System;
using System.Collections.Generic;
using System.ServiceModel.Description;
using Microsoft.ServiceModel.Http;
using Nina.ViewEngines;
namespace Http.Formatters
{
public class ViewEngineProcessor<T> : GenericMediaTypeProcessor<T>
{
private static readonly IDictionary<string, ITemplate> _cache = new Dictionary<string, ITemplate>();
private readonly string _basePath;
public ViewEngineProcessor(HttpOperationDescription operation, MediaTypeProcessorMode mode, string basePath = "Views/")
: base(operation, mode)
{
_basePath = basePath;
}
public override IEnumerable<string> SupportedMediaTypes
{
get
{
yield return "text/html";
//yield return "application/xhtml+xml";
}
}
public override object ReadFromStream(System.IO.Stream stream, System.Net.Http.HttpRequestMessage request)
{
throw new NotImplementedException();
}
public override void WriteToStream(T instance, System.IO.Stream stream, System.Net.Http.HttpRequestMessage request)
{
ITemplate template;
string templateName = _basePath + typeof(T).Name;
Type modelType = instance.GetType();
if (Nina.Configuration.Configure.IsDevelopment || !_cache.TryGetValue(templateName, out template))
{
template = Nina.Configuration.Configure.Views.Engine.Compile<T>(templateName);
_cache[templateName] = template;
}
using (var sw = new System.IO.StreamWriter(stream.PreventClose()))
{
template.Render(sw, instance);
sw.Flush();
}
}
}
}

All this is available in the WCF HTTP Contrib project. I’m sure it will develop into something a bit nicer as we progress. Also, I want to cover channels at some point, as they will offer a nicer composition mechanism for things like security, general logging, and other common middleware patterns found in the projects mentioned above.

Have you tried the WCF Web APIs? If so, please leave the team some feedback. They’d love to hear from you. Check out the contrib project while you’re at it. Want to see something in particular? File a case or contribute. And thank Darrel Miller for setting it up!

*[conneg]: content negotiation

A New Web for .NET: WCF Web APIs

If the sight of “WCF” in the title makes you want to click your back button, stop. Just wait. I tell you that I have been there, too. This isn’t that WCF. Well, it is, sort of. If you listened to our last several podcasts, you heard Glenn Block talk about his transition from MEF to the WCF team and that he was going to be working on REST. Well, it’s here. Before you continue reading, I recommend you:

  1. Download the bits
  2. Read Glenn’s posts (yes, there is a link in that last one on how to wire up the Razor view engine)
  3. Watch the RESTFest keynote and video

I know, That’s probably asking a lot. I promise, you won’t be disappointed. The WCF team has done a bang up job on this, and it’s continuing to improve. For my part, I’ve been working on making the transition to F# smoother.

Why am I excited about this? I see the new Web APIs as a fantastic, Rack+Sinatra-like platform for .NET. No, it’s not exactly the same, but it fulfills a very similar function. The new Web APIs give you a to-the-metal experience, with control over everything in a statically-typed environment. (Yes, even the headers!) A lot of the WCF abstraction has been stripped away so that HTTP, the application protocol, is available in its fullness.

“Sounds great,” you say, but I already have MVC for that. True, and yes, you can do JSON services with MVC. However, HTTP is primarily a messaging protocol, which WCF fits nicely. MVC is primarily an abstraction for building web pages in HTML. So again, yes there is overlap. Give it a whirl, however, and you’ll probably start seeing, as so many in the Ruby community, that the simpler abstraction offered by the WCF Web APIs is more efficient for REST services and even web application environments. (More on that last part towards the end of the series.)

Simple, yes, but you can already see the same power offered by Rack. Middleware is just a step around the corner. A simple Sinatra-like DSL would make this trivially easy to compose application parts. The WCF Web APIs will offer a composition mechanism, though that is still in the works.

What do I mean? Well, let’s look at a trivial example:

For completeness, here’s the FuncHost wrapper and other type declarations I’m using:


module Main
open System
open System.Collections.Generic
open System.Net
open System.Net.Http
open Microsoft.ServiceModel.Http
open FSharp.Http
[<EntryPoint>]
let main(args) =
let app (request:HttpRequestMessage) = async {
// do some stuff with the request
return "200 OK", Seq.empty, "Howdy!"B |> Seq.map (fun b -> b :> obj) }
let processors = [| (fun op -> new PlainTextProcessor(op, MediaTypeProcessorMode.Response) :> System.ServiceModel.Dispatcher.Processor) |]
let host = new FuncHost(app, responseProcessors = processors, baseAddresses = [|"http://localhost:1000/&quot;|])
host.Open()
printfn "Host open. Hit enter to exit…"
printfn "Use a web browser and go to %sroot or do it right and get fiddler!" baseurl
System.Console.Read() |> ignore
host.Close()
0

view raw

FSharpServer.fs

hosted with ❤ by GitHub


namespace FSharp.Http
open System
open System.Collections.Generic
open System.Net
open System.Net.Http
open System.ServiceModel
open System.ServiceModel.Web
// NOTE: This is not the actual OWIN definition of an application, just a close approximation.
type Application = Action<HttpRequestMessage, Action<string, seq<KeyValuePair<string,string>>, seq<obj>>, Action<exn>>
module Owin =
let fromAsync (app:HttpRequestMessage -> Async<string * seq<KeyValuePair<string,string>> * seq<obj>>) : Application =
Action<_,_,_>(fun request (onCompleted:Action<string, seq<KeyValuePair<string,string>>, seq<obj>>) (onError:Action<exn>) ->
Async.StartWithContinuations(app request, onCompleted.Invoke, onError.Invoke, onError.Invoke))
/// <summary>Creates a new instance of <see cref="Processor"/>.</summary>
/// <param name="onExecute">The function to execute in the pipeline.</param>
/// <param name="onGetInArgs">Gets the incoming arguments.</param>
/// <param name="onGetOutArgs">Gets the outgoing arguments.</param>
/// <param name="onError">The action to take in the event of a processor error.</param>
/// <remarks>
/// This subclass of <see cref="System.ServiceModel.Dispatcher.Processor"/> allows
/// the developer to create <see cref="System.ServiceModel.Dispatcher.Processor"/>s
/// using higher-order functions.
/// </remarks>
type Processor(onExecute, ?onGetInArgs, ?onGetOutArgs, ?onError) =
inherit System.ServiceModel.Dispatcher.Processor()
let onGetInArgs' = defaultArg onGetInArgs (fun () -> null)
let onGetOutArgs' = defaultArg onGetOutArgs (fun () -> null)
let onError' = defaultArg onError ignore
override this.OnGetInArguments() = onGetInArgs'()
override this.OnGetOutArguments() = onGetOutArgs'()
override this.OnExecute(input) = onExecute input
override this.OnError(result) = onError' result
/// <summary>Creates a new instance of <see cref="FuncConfiguration"/>.</summary>
/// <param name="requestProcessors">The processors to run when receiving the request.</param>
/// <param name="responseProcessors">The processors to run when sending the response.</param>
type FuncConfiguration(?requestProcessors, ?responseProcessors) =
inherit Microsoft.ServiceModel.Http.HttpHostConfiguration()
// Set the default values on the optional parameters.
let requestProcessors' = defaultArg requestProcessors Seq.empty
let responseProcessors' = defaultArg responseProcessors Seq.empty
// Allows partial application of args to a function using function composition.
let create args f = f args
interface Microsoft.ServiceModel.Description.IProcessorProvider with
member this.RegisterRequestProcessorsForOperation(operation, processors, mode) =
requestProcessors' |> Seq.iter (processors.Add << (create operation))
member this.RegisterResponseProcessorsForOperation(operation, processors, mode) =
responseProcessors' |> Seq.iter (processors.Add << (create operation))
/// <summary>Creates a new instance of <see cref="AppResource"/>.</summary>
/// <param name="app">The application to invoke.</param>
/// <remarks>The <see cref="AppResource"/> serves as a catch-all handler for WCF HTTP services.</remarks>
[<ServiceContract>]
[<ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)>]
type AppResource(app:Application) =
let matchStatus (status:string) =
let statusParts = status.Split(' ')
let statusCode = statusParts.[0]
Enum.Parse(typeof<HttpStatusCode>, statusCode) :?> HttpStatusCode
let handle (request:HttpRequestMessage) (response:HttpResponseMessage) =
app.Invoke(request,
Action<_,_,_>(fun status headers body ->
response.StatusCode <- matchStatus status
response.Headers.Clear()
headers |> Seq.iter (fun (KeyValue(k,v)) -> response.Headers.Add(k,v))
response.Content <- new ByteArrayContent(body |> Seq.map (fun o -> o :?> byte) |> Array.ofSeq)),
Action<_>(fun e -> Console.WriteLine(e)))
/// <summary>Invokes the application with the specified GET <paramref name="request"/>.</summary>
/// <param name="request">The <see cref="HttpRequestMessage"/>.</param>
/// <returns>The <see cref="HttpResponseMessage"/>.</returns>
/// <remarks>Would like to merge this with the Invoke method, below.</remarks>
[<OperationContract>]
[<WebGet(UriTemplate="*")>]
member x.Get(request, response:HttpResponseMessage) = handle request response
/// <summary>Invokes the application with the specified GET <paramref name="request"/>.</summary>
/// <param name="request">The <see cref="HttpRequestMessage"/>.</param>
/// <returns>The <see cref="HttpResponseMessage"/>.</returns>
[<OperationContract>]
[<WebInvoke(UriTemplate="*", Method="POST")>]
member x.Post(request, response:HttpResponseMessage) = handle request response
/// <summary>Invokes the application with the specified GET <paramref name="request"/>.</summary>
/// <param name="request">The <see cref="HttpRequestMessage"/>.</param>
/// <returns>The <see cref="HttpResponseMessage"/>.</returns>
[<OperationContract>]
[<WebInvoke(UriTemplate="*", Method="PUT")>]
member x.Put(request, response:HttpResponseMessage) = handle request response
/// <summary>Invokes the application with the specified GET <paramref name="request"/>.</summary>
/// <param name="request">The <see cref="HttpRequestMessage"/>.</param>
/// <returns>The <see cref="HttpResponseMessage"/>.</returns>
[<OperationContract>]
[<WebInvoke(UriTemplate="*", Method="DELETE")>]
member x.Delete(request, response:HttpResponseMessage) = handle request response
/// <summary>Invokes the application with the specified GET <paramref name="request"/>.</summary>
/// <param name="request">The <see cref="HttpRequestMessage"/>.</param>
/// <returns>The <see cref="HttpResponseMessage"/>.</returns>
[<OperationContract>]
[<WebInvoke(UriTemplate="*", Method="*")>]
member x.Invoke(request, response:HttpResponseMessage) = handle request response
/// <summary>Creates a new instance of <see cref="FuncHost"/>.</summary>
/// <param name="app">The application to invoke.</param>
/// <param name="requestProcessors">The processors to run when receiving the request.</param>
/// <param name="responseProcessors">The processors to run when sending the response.</param>
/// <param name="baseAddresses">The base addresses to host (defaults to an empty array).</param>
type FuncHost(app, ?requestProcessors, ?responseProcessors, ?baseAddresses) =
inherit System.ServiceModel.ServiceHost(AppResource(app), defaultArg baseAddresses [||])
let requestProcessors = defaultArg requestProcessors Seq.empty
let responseProcessors = defaultArg responseProcessors Seq.empty
let baseUris = defaultArg baseAddresses [||]
let config = new FuncConfiguration(requestProcessors, responseProcessors)
do for baseUri in baseUris do
let endpoint = base.AddServiceEndpoint(typeof<AppResource>, new HttpMessageBinding(), baseUri)
endpoint.Behaviors.Add(new Microsoft.ServiceModel.Description.HttpEndpointBehavior(config))
/// <summary>Creates a new instance of <see cref="FuncHost"/>.</summary>
/// <param name="app">The application to invoke.</param>
/// <param name="requestProcessors">The processors to run when receiving the request.</param>
/// <param name="responseProcessors">The processors to run when sending the response.</param>
/// <param name="baseAddresses">The base addresses to host (defaults to an empty array).</param>
new (app: HttpRequestMessage -> Async<string * seq<KeyValuePair<string,string>> * seq<obj>>, ?requestProcessors, ?responseProcessors, ?baseAddresses) =
let baseUris = defaultArg baseAddresses [||] |> Array.map (fun baseAddress -> Uri(baseAddress))
new FuncHost(Owin.fromAsync app, ?requestProcessors = requestProcessors, ?responseProcessors = responseProcessors, baseAddresses = baseUris)

view raw

FuncHost.fs

hosted with ❤ by GitHub

Go try it out. Let the team know what you think! If you want to show off what you are doing, consider sending a pull request to http://wcfhttpcontrib.codeplex.com/, where we’ll be adding middleware and other common components for your convenience. More on middleware next time.

A New Web for .NET

A number of things have been happening these last few years in the .NET community in relation to the Web. Specifically, OpenRasta and FubuMvc demonstrated 1) new approaches to web development in a static-typed world and 2) that other developers were growing tired of the existing options. Since then a host of new micro-frameworks, generally inspired by the Ruby dynamic duo of Rack and Sinatra, have popped up on github. In addition, several new server options have begun cropping up, most notably Kayak and Manos de Mono, both of which use an event loop a la node.js and primarily targeting Mono.

Microsoft has not be sitting idly by either. The WCF team is working on a new Web API to provide WCF developers simpler, more direct control over HTTP services. This is no slouch effort either. In fact, aside from OpenRasta, it may be the most thorough HTTP implementation available.

While exciting on their own, the best news, imho, is the .NET HTTP Abstractions group, started by Scott Koon. This group has been working on a standard, currently called Open Web Interface for .NET, or OWIN. It’s intent is to define a common interface by which any application can talk to any server. The idea comes from the Web Server Gateway Interface (Python) and Rack. The primary difference in this and other similar specs is the inclusion of asynchronous network I/O as a primary concern. Discussions are still underway and include nearly all of the developers of the aforementioned projects, as well as some members of the ASP.NET team.

If you are a F# fanboy, such as myself, you will be happy to know that F# is not silent in this space. WebSharper is now in its second iteration, and my own projects, Frack and Frank, are making nice headway. Frack is now a web server, similar in spirit to node.js. Frank is, as the name implies, a Sinatra-inspired clone that takes cues from the Haskell Snap framework. If you are interested in parsing and agent-based development, you’ll find more examples of how F# handles these things as these two projects progress.

Expect to find more posts (shock!) coming soon describing in more detail the WCF Web APIs, OWIN, Frack, Frank, and more. In the meantime, join the discussion on the .NET HTTP Abstractions group!