Monday, January 23, 2012

Getting Started with FubuMVC

With FubuMVC getting closer and closer to version 1.0, more and more developers are adopting it for its conventional design and the ability to control all aspects of its behavior.  I started using FubuMVC 4 months ago and ran into many road blocks as there wasn’t (And currently as of this post “isn’t”) very much documentation on how to get started and what you can do.  I would like to spend the next few weeks writing up posts on how to first get Fubu up and running, then how to use its conventional power and the underlying magic within.  I say magic because it is what it is, the framework is simply brilliant and I want to demonstrate it’s power little by little over each post.  There are currently two ways you can configure FubuMVC for a new project, one would be to download the Nuget package “FubuMVC”

image

 

This is basically the Starter package which will load all the references and get FubuMVC configured and Setup for you.  Im not going to cover that route as it’s pretty straight forward and easy for anyone to get started.  What I want to demonstrate is the manual approach to configuring FubuMVC.  For me its always better to get your hands dirty and really learn how to use your tools and what they truly do under the hood.  So lets begin.

Create a new ASP.NET Web project (Empty).

image

Next, right click on your references and select Manage NuGet packages, you should get the same screen as the NuGet image above.  Type in FubuMVC in the search and choose FubuMVC.References and FubuMVC.Spark.  This will load all the required references you need to get Fubu up and running.  Lets assume I created my project as MyFubu.  First step we need is to get Fubu bootstrapped and registered.  Create a class in your web project, for me I might call it MyFubuApplication keeping it named after my project.

public class MyFubuApplication : IApplicationSource
{
    public FubuApplication BuildApplication()
    {
        return FubuApplication
            .For<MyFubuRegistry>()
            .StructureMap(WebBootstrapper.BuildContainer);
    }
}







Now we need to create our registry class and our web bootstrap class.



public class MyFubuRegistry : FubuRegistry
{
    public MyFubuRegistry()
    {
        IncludeDiagnostics(true);
        Applies
            .ToThisAssembly();
        Actions
            .IncludeTypesNamed(name => name.ToLower().EndsWith("endpoint"));
        
        Routes
            .HomeIs<MyHomeEndpoint>(e => e.Index(null))
            .IgnoreControllerNamesEntirely();
        Views
            .TryToAttachWithDefaultConventions();
        this.UseSpark();
    }
}


and for our bootstrap class, this is where you educate Structuremap on where your Registry classes are:



public static class WebBootstrapper
{
    public static IContainer BuildContainer()
    {
        ObjectFactory.Initialize(x =>
        {
            x.AddRegistry<WebRegistry>();
        });
        return ObjectFactory.Container;
    }
}
public class WebRegistry : Registry
{
    public WebRegistry()
    {
        Scan(x =>
        {
            x.TheCallingAssembly();
            x.WithDefaultConventions();
        });
    }
}


As you can see in the FubuRegistry I set the route of HomeIs<MyHomeEndpoint>, what this is telling fubu is when the site loads to direct the user to the default landing page which is in MyHomeEndpoint.Index.  That class would look something like this:



public class MyHomeEndpoint
{
    public HomeViewModel Index(HomeViewModel input)
    {
        return input;
    }
}
public class HomeViewModel
{
    public string HelloWorld
    {
        get { return "Hello World";}
    }
}


Now all I would need is a spark file that uses my HomeViewModel as its model and FubuMVC will build a route to this view which would look something like MyHomeEndpoint/Index. Now this looks a bit tacky having the word endpoint in your url. Not a problem, Fubu allows you to control the way your routes display. To override the way FubuMVC creates your routes simply create a class that inherits IUrlPolicy, something like the following:



public class EndpointUrlPolicy : IUrlPolicy
{
    public bool Matches(ActionCall call)
    {
        return call.HandlerType.Name.EndsWith("Endpoint");
    }
    public IRouteDefinition Build(ActionCall call)
    {
        var routeDefinition = call.ToRouteDefinition();
        routeDefinition.Append(call.HandlerType.Namespace.Replace(GetType().Namespace + ".", string.Empty).ToLower());
        routeDefinition.Append(call.HandlerType.Name.Replace("Endpoint", string.Empty).ToLower());
        return routeDefinition;
    }
}


And register this in your FubuRegistry class



Routes.UrlPolicy<EndpointUrlPolicy>();


And that’s it, your new route policy is in effect and now our url is rendered as /MyHome/Index.  Further customization could be performed to remove the Index as well if desired.



This covers the setting up of FubuMVC portion, to make sure your routes are wired up correctly, run your application and go to localhost:YOURPORT/_fubu to see the advanced diagnostics.  Click on the Behavior Chains link and check that your routes (Mine would be MyHome/Index) are present.  You can also click on the Behavior chain link next to the route to see how Fubu wired it up.  The Advanced Diagnostics will quickly become your closest friend when working with Fubu as it informs you of any chains that are not correctly routed and helps you understand why they are not working as you desired them too.



This about sums it up for getting started, go check out FubuMVC for yourself and see what you think about it.



The FubuMVC Project



Happy Coding!

3 comments:

Kijana Woodard said...

Thanks for doing this overview Gary. It helped me get some things working using "Endpoint" instead of "Controller".

However, that was using the full FubuMVC starter kit.

I think I'm missing how to hook up the 'IApplicationSource'. I tried adding a call in global.asax (which doesn't seem right), but the 'FubuRegistry' was never invoked in that case.

I noticed that the full starter kit made some web.config changes. Are any of those entries needed for this solution?

Kijana Woodard said...

Of course the moment I posted my comment, I got an idea that pushed me along.

I added the following to app_start in global.asax and everything works.

new FubuKataApplication().BuildApplication().Bootstrap();

I expect you didn't intend the 'IApplicationSource' to be newed up. How do you inform Fubu about it.

Thanks again.

Gary Cox said...

I must have missed that piece, the way you did is correct.

protected void Application_Start(object sender, EventArgs e)
{
new MyFubuApplication()
.BuildApplication()
.Bootstrap();
}

 
Creative Commons License
Blogged Information and Code is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.