Building a Simple FubuMVC Convention

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.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in FubuMVC. Bookmark the permalink. Follow any comments here with the RSS feed for this post.