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.

Last edited Aug 22, 2010 at 2:29 PM by stovellp, version 3

Comments

No comments yet.