Wiki

Clone wiki

TakeIo.Essentials / Home

Take.io Essentials

Take.io Essentials is a RESTful Framework for ASP.NET MVC 3.

This project is under active development, and the following presentation shows up the tested basics:

Basic features

  • Built on top of ASP.NET MVC 3 and Common Service Locator
  • Sinatra-like RESTful Routes, with support to unify several controllers in a single ASP.NET application using a MapRouteTable() function to inherit configuration from Web.config
  • Added support for HEAD and OPTIONS methods
  • Syntax-sugar for returning OpenSocial-like items and collections (JSON/XML), resource creation and removal
  • User-friendly exception handlers
  • Requests profiling module (timing for web requests)
  • "Safe" calls to Common Service Locator
  • Simple access to logging facility
  • Included "Design by Contract" (i.e. calls to Check.* functions)
  • Model Binder for array data in query string
  • Cache of items and collections
  • Support for legacy browsers (i.e. use of "_method" query-string parameter)

Advanced features

  • Support to Federated Authentication using X-PF HTTP header; this permits modules written in another environments reuse the same authentication used in your base platform in a secure way and assure that 'internal requests' doesn't loop
  • Unit testing tools: simulate Web requests without having to instantiate a full Web Server (HttpSimulator).

Sinatra-like Routing

1) Call the extension function MapRouteTable() in Global.asax.cs's Application_Start():

using TakeIo.Web;

public class MvcApplication : HttpApplication
{
    protected void Application_Start()
    {
        // You can call other RouteTable.Routes methods here
        // ...

        // But using this order, you will overwrite the above in Web.config
        RouteTable.Routes.MapRouteTable();
    }
}

2) This way, you can map several controllers in the same ASP.NET application. Just use the routeTable configuration section:

<configuration>
  <configSections>
    <sectionname="routeTable" type="TakeIo.Web.RouteTableSection, TakeIo.Web" />
  </configSections>
  ...
  <routeTable>
    <routes>
      <!--
        The code below will prefix SomePrefix for all controllers available
        in SomeAssembly assembly. If you don't want any prefix, just set
        an empty string in 'path' attribute.
       -->
      <addname="RouteName" path="SomePrefix" assembly="SomeAssembly" />
    </routes>
  </routeTable>
  ...
</configuration>

3) When you aim MVC 3 with an IoC container, you must register all controllers in IoC too. For example, if you're using Castle Windsor in your application, just include the following in your Web.config file (suppose you have a controller named MyController, in assembly MyAssembly, with namespace MyAssembly.Namespace.MyController):

  <component
        id="MyAssembly.Namespace.MyController"
        type="MyAssembly.Namespace.MyController, MyAssembly"
        lifestyle="transient" />

Castle Windsor IoC support for MVC 3

1) To register an IoC Controller Factory in MVC 3 based on Castle Windsor, derive your HttpApplication from WindsorApplication and call BootstrapControllerBuilder(). Note: when you do this, you will need to register all controller instances in IoC container, see below.

using TakeIo.Web.Castle

public class MyApplication : WindsorApplication
{
    protected void Application_Start()
    {
        // ...
        BootstrapControllerBuilder();
        // ...
    }
}

2) To register all Controllers available in current assembly in Castle Windsor (just like the way you obtain when you don't use an IoC Controller Factory), just try the code below. You can try to pass in other assemblies too, just select it using Assembly static calls.

using TakeIo.Web.Castle

public class MyApplication : WindsorApplication
{
    protected void Application_Start()
    {
        // ...
        BootstrapControllersFromAssembly(Assembly.GetExecutingAssembly());
        // ...
    }
}

3) If you have IWindsorInstaller classes in your code, you can register them statically using the BootstrapWindsorInstallers() call. Just pass in the available instances:

using TakeIo.Web.Castle

public class MyApplication : WindsorApplication
{
    protected void Application_Start()
    {
        // ...
        BootstrapWindsorInstallers(new MyWindsorInstaller(), ...);
        // ...
    }
}

4) If you want to have a dependencies.config file to (possibly) override instantiation of your application, you can call BootstrapDependenciesConfig().

using TakeIo.Web.Castle

public class MyApplication : WindsorApplication
{
    protected void Application_Start()
    {
        // ...
        BootstrapDependenciesConfig();
        // ...
    }
}

If you want to register you controllers by hand in your dependencies.config, just add the following directive:

<configuration>
    <components>
        <!-- ... -->
        <component
            id="MyAssembly.Namespace.MyController"
            type="MyAssembly.Namespace.MyController, MyAssembly"
            lifestyle="transient" />
        <!-- ... -->
    </components>
</configuration>

5) If you want to register this same instance of the Castle Windsor kernel to Common Service Locator, call BootstrapServiceLocator().

using TakeIo.Web.Castle

public class MyApplication : WindsorApplication
{
    protected void Application_Start()
    {
        // ...
        BootstrapServiceLocator();
        // ...
    }
}

Full example using Castle Windsor in TakeIo.Essentials

The following example uses the main concepts listed above.

public class MvcApplication : WindsorApplication
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        // these maps routes only, don't forget to register componentes
        // in Castle Windsor if you have registered a Controller Builder.
        routes.MapAssembly(Assembly.GetExecutingAssembly());

        // maps http://domain.com/somePrefix/pathInControllerAttributes
        routes.MapAssembly(Assembly.GetExecutingAssembly(), "somePrefix");

        // maps routes from Web.config
        routes.MapRouteTable();
    }

    public void RegisterWindsorContainer()
    {
        // register Controllers from current assembly
        BootstrapControllersFromAssembly(Assembly.GetExecutingAssembly());

        // bootstrap a Windsor Controller Builder
        BootstrapControllerBuilder();

        // override static configuration using 'dependencies.config' file
        BootstrapDependenciesConfig();

        // register the current Castle Windsor instance to CSL
        BootstrapServiceLocator();
    }

    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);
        RegisterWindsorContainer();
    }
}

Updated