Archives

Archives / 2008 / January
  • ASP.Net MVC Framework - Assign a ViewFactory to a Controller

    I have seen several posts about how to assign a ViewFactory to a Controller, most of the case the code looks like this:


    public class HomeController : Controller
    {
        public HomeController()
        {
           this.ViewFactory = new MyViewFactory();
        }
    }

    The ViewFactory is assigned into the constructor of a Controller. If we want to use the same ViewFactroy for all Controllers in out app, we can for example create a new base class for our Controller:


    public class MyController : Controller
    {
         public MyContoroller()
         {
             this.ViewFactory = new MyViewFactory();
         }
    }

    public class HomeController : MyController
    {
         public HomeController() : base()
         {
         }
    }


    I’m a more fan of making this configurable via a configuration file, to map a ViewFacotry to a Controller, this can for example be done with Spring.Net:


    <?xml version="1.0" encoding="utf-8" ?>
    <objects xmlns="http://www.springframework.net"
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://www.springframework.net http://www.springframework.net/xsd/spring-objects.xsd">

      <object id="HomeController" type="MvcApplication.Controllers.HomeController, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">
        <constructor-arg name="viewFactory" ref="MyFactory"/>
      </object>

      <object id="MyFactory" type="MyViewFactory, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
     
    </objects>


    Note: You can read my other post about using Spring.Net to create Controllers.


    public class HomeController : Controller
    {
       public HomeController() : this(new DefaultViewFactory ()) {}
       public HomeController(IViewFactory viewFactory)
       {
           this.ViewFactory = viewFactory;
       }
     }


    There a so many different solutions to set a ViewFactory during creation of a Controller, for example by creating an own ControllerFactory, the following code is from my post about writing your own IRoutHandler:


    public IController CreateController(RequestContext context, string controllerName)
     {
            //I should refactor out the following two lines to not only make sure to make the creation of the ObjectFactory once.
            IResource input = new FileSystemResource(context.HttpContext.Request.MapPath("objects.xml"));
            IObjectFactory factory = new XmlObjectFactory(input);

            IController controller = (IController)factory.GetObject(controllerName, typeof(IController));

            if (typeof(Controller).IsAssignableFrom(controller.GetType()))
            {
              N2MVCConfigurationHandler config = ConfigurationManager.GetSection("Nsquared2/N2MVCSection") as N2MVCConfigurationHandler;
              ((Controller)controller).ViewFactory = N2ViewFactoryBuilder.GetViewFactory(config.ViewFactory);
            }

            return controller;
    }


    What this code does, is to see if the Controller is assigned from the Controller class, ugly code, I know, but it’s only the Controller base class that has the ViewFactory property, and we can create a Controller which only implements the IController interface, and this interface don’t have the ViewFactory property.

    The code above will get the ViewFactory from a configuration file:


    <Nsquared2>
        <N2MVCSection
            controllerFactory="MvcApplication.Models.N2ControllerFactory, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
            viewFactory="MvcApplication.Models.N2ViewFactory, MvcApplication, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
    </Nsquared2>


    In this example I assume that every Controller use the same ViewFactory, and that may not always be the case, so in that case the earlier example by using Spring.Net an inject a ViewFactory would be better use, or creating a new ControllerFactory which will map a Controller to a ViewFactory, so when the ControllerFactory creates the Controller, the factory could look up in a config file to see, which ViewFactory should be used for the specific Controller, for example:


    <Controllers defaultViewFactory=”myViewFactory”>
        <add name=”HomeController” ViewFactory=”myOwnViewFactory” …>
    </Controllers>


    What is the main goal with these kinds of solutions? Well we can now simply change the ViewFactory for our Controller without recompiling our code, and we will also remove the dependency from a Controller and the ViewFactory by not hard code the instantiation within the Controllers. I prefer Interface Driven Programming and the use of factories, and the possibility to easy configure the use of classes etc in a configuration file. That is why I also loved the Provider based solution that was shipped with ASP.Net 2.0, like the Membership and Roles features etc.

    Read more...