Building a Simple FubuMVC Convention | Jeremy D. Miller

:

I will fix the *&^%*ing code formatting later.

In my last missive I gave a high level explanation of FubuMVC’s configuration strategy.  Before going deep into the details, let’s look at a simple example that demonstrates both the runtime and configuration architecture of FubuMVC.  I’m going to push this into FubuMVC.Core afterwards.

A friend of mine recently worked on a project where they were building several Json endpoints with a REST inspired architecture.  Most of their endpoints took in a message, did something, then simply returned an Http status code to denote success or failure.

Let’s say that you are building that same system the “FubuMVC way,” meaning we want FubuMVC to take care of the consistent actions like deserializing json and writing the status code to the http response.  Using the idea of “one model in, one model out,” all of my actions would take in the input message and just return an System.Net.HttpStatusCode object like this one:

// JsonMessage is just a marker interface
// FubuMVC doesn't yet support "conneg" -- but should
// We take pull requests!
public class InputMessage : JsonMessage {}

public class RestfulService
{
    public HttpStatusCode Action1(InputMessage message)
    {
        // perform the action
        return HttpStatusCode.OK;
    }
}

When I unit test that service method above I can simply assert that the status code returned matches what I expected for the input message.  No FubuMVC internals to get in the way.

As of now, FubuMVC doesn’t know how to handle actions that return just an HttpStatusCode.  We’ll need to build out two pieces, a runtime behavior that writes the status code and a convention that puts this runtime behavior in the chain after the right actions.

The runtime is pretty simple, it’s just this little class here that implements the IActionBehavior interface:

    public class RenderStatusCodeBehavior : IActionBehavior     {         private readonly IFubuRequest _request;         private readonly IOutputWriter _writer;         public RenderStatusCodeBehavior(IFubuRequest request, IOutputWriter writer)
        {             _request = request;             _writer = writer;         }         public void Invoke()         {             // There is a T Get<T>() method on IFubuRequest, but in             // my infinite wisdom I made it so that it only works              // for reference types             var status = (HttpStatusCode)_request.Get(typeof (HttpStatusCode));
            _writer.WriteResponseCode(status);         }         public void InvokePartial()         {             Invoke();         }     }

Now that the runtime works we just need to add some conventions to the FubuRegistry for the application like this:

    public class RestfulServicesRegistry : FubuRegistry     {         public RestfulServicesRegistry()         {           // Need to tell FubuMVC which classes are actions           Actions.IncludeTypes(x => x.IsInNamespace("RestfulStatusCodeServices"));
          // Tell FubuMVC to toss the RenderStatusCodeBehavior on  // the back of any behavior chain where the action returns  // an HttpStatusCode           Output.ToBehavior<RenderStatusCodeBehavior>()               .WhenTheOutputModelIs<HttpStatusCode>();
          Routes               .ConstrainToHttpMethod(x => x.OutputType() == typeof(HttpStatusCode), "POST")
              .IgnoreControllerNamespaceEntirely();         }     }

 

That wasn’t horrible now was it?  This most certainly is not everyday FubuMVC usage, but when you do need to tailor the way FubuMVC works for your project, you can.

P.S. This is going into FubuMVC’s default conventions, so you don’t need to build this yourself or even copy the code.