arrow-left arrow-right brightness-2 chevron-left chevron-right circle-half-full dots-horizontal facebook-box facebook loader magnify menu-down RSS star Twitter twitter GitHub white-balance-sunny window-close
Magellan Controllers
3 min read

Magellan Controllers

This is an old post and doesn't necessarily reflect my current thinking on a topic, and some links or images may not work. The text is preserved here for posterity.

Back to: Magellan Home

As an MVC framework, controllers are the most prominent object in Magellan. At their simplest, controllers are implemented as classes, and actions are implemented as methods on the class. Actions on a controller must be public methods, and must return ActionResult objects. Here is an example:

public class CustomerController : Controller
{
    public ActionResult Index()
    {
        Model = Customers.GetAll();
        return Page();
    }

    public ActionResult Show(int customerId) 
    {
        Model = Customers.Get(customerId);
        return Page();
    }
}

This page describes how controllers are executed.

Controller Factories

Navigation begins at the Navigator, either by using a command, behavior or calling it explicitly. The Navigator processes the request by resolving a controller from the controller factory, executing the request, and releasing the controller back to the factory:

public void Navigate(NavigationRequest request)
{
    Guard.ArgumentNotNull(request, "request");

    var controllerFactory = ControllerBuilder.Current.GetControllerFactory();
    var controllerResult = controllerFactory.CreateController(request, request.Controller);
    var controller = controllerResult.Controller;
    var context = new ControllerContext(controller, request, controllerResult.Release);
    controller.Execute(context);
}

The controller factory implements the IControllerFactory interface, and provides a method to resolve the controller:

public interface IControllerFactory
{
    ControllerFactoryResult CreateController(NavigationRequest request, string controllerName);
}

The controller factory is set via the ControllerBuilder.Current.SetControllerFactory method. See the topic on using an IOC container for an example on creating your own controller factory.

Controllers

The controllers returned by the controller factory must implement the IController interface, which is quite simple:

public interface IController
{
    void Execute(NavigationRequest request);
}

The NavigationRequest passed to the controller contains information about the controller name, action name, and any parameters for the request. It is up to the controller to decide how to handle the request given this information. If the class/method convention used by Magellan isn't enough, your controller can use different mechanisms to prosecute the request. Magellan's navigator, behaviors, and commands can still be used.

Controllers will usually derive from the Controller base class. When this controller executes a request, it will work with an action invoker to resolve the action, call any action filters, execute the action, and evaluate the result.

The Execute method on the Controller base class is quite simple:

public void Execute(NavigationRequest request)
{
    Request = request;
    ActionInvoker.ExecuteAction(ControllerContext, request.Action, ModelBinders);
}

To make writing controllers easy, a number of helper methods exist for creating the action results, such as View(), Cancel() and Redirect(). You can read more about them in the action results section.

Action Invoker

The action invoker is used by the controller to handle the details of executing the action. This allows you to continue to derive from the Controller class while executing actions in a very different way. By default, the controller's ActionInvoker property is set to the DefaultActionInvoker.

The default action invoker uses reflection to map the requests Action property to a method on the controller. It then performs the following steps:

  1. Executes all pre-action filters
  2. Executes the action
  3. Executes all post-action filters
  4. Executes the action result

Action filters provide a way for you to implement cross-cutting concerns on controllers, such as authorization, logging, state management, and other examples.

When the action has been executed, it will return an Action Result. This is an important point - controllers do not show views directly, they simply return an object which is responsible for resolving and showing the view. This allows you handle the navigation request in a very different way without altering controllers.

Model Binders

One of the tasks the action invoker takes care of is mapping parameters from the current NavigationRequest to arguments passed to the action method on the controller. Rather than putting this logic in the action invoker, it instead calls through to objects known as Model Binders.

The ModelBinders.Binders static property is a registry of active model binders, associated with a type. By default there is only one binder - a DefaultModelBinder which uses type descriptors and casting to perform the conversion. If you wish to customize how request parameters are mapped to action method parameters, you can do so through implementing the IModelBinder interface and registering it with the ModelBinders.Binders collection.

See also:

Back to: Magellan Home

Paul Stovell's Blog

Hello, I'm Paul Stovell

I'm a Brisbane-based software developer, and founder of Octopus Deploy, a DevOps automation software company. This is my personal blog where I write about my journey with Octopus and software development.

I write new blog posts about once a month. Subscribe and I'll send you an email when I publish something new.

Subscribe

Comments