A CRUD action provider

As it was described in the previous entry, the idea of the action providers is to allow to gather cross-cutting concerns into more generic (not in the C# terms, but functionalities/features) bag than a derivation from a generic controller. To provide a working example, a standard CRUD operations can be taken into the consideration. Let’s take a look into another gist.
I do hate static code, but for sake of a simplicity all the CRUD operations were moved to a static class, CrudActions. All of them are pretty simple, as they use an entity model binder introduced in the former blog entries. For instance, when an entity edit result is posted to the server, a model binder will take care of updating the entity, so the entity being passed to the [HttpPost]Edit will be already altered with the changes made by a user.
The very second step was discovering all of the CrudActions. It is made by a DetachedActionProvider which caches information in a ReadWriteCache taken from the MVC internals. To close the open generic of CrudActions, an entity type with an id’s type is needed. The entity type information is retrieved from a IEntityController, which is a simple markup convention (you can come up with a name convention, or delegate it somewhere else), for attaching to a controller a handled entity type. The id metadata are gathered from the NHibernate’s ISessionFactory. Once the data are retrieved, the CrudActions generic class definition can be turned into a closed generic and the specific method can be found.
Wait a second… how do we transform a MethodInfo into an ActionDescriptor? First, the method infos are wrapped with an ActionInfo instance (it caches attributes as well as the method info itself). Next, the ActionInfos, those who applies (HttpGet, HttpPost, etc.), are passed to the ReflectedMvc to create a ReflectedActionDescriptor.
At the end I left some bitterness about MVC internalization policy. I must admit, that I don’t understand internalizing types or constructors or any members which could be helpful for future app development. That case applies to the ReflectedActionDescriptor ctor, which (the public one) throws an exception if the method passed to it is a static method. The other, non-checking one, is of course internalized. I’m asking: why? The internalization should be used as a last resort, no as a ‘hide it, because I cannot predict if someone doesn’t want to crush MVC in his project’ rule.

Hope you like the action provider extension point and will use it for cross-cutting, ‘I can compose, not only derive from a generic class’ actions in your controllers.

An action provider, other than controller

Yep, that’s another post in a series which will finally bring so-called detached actions to live. Today I’ll introduce the concept of action providers, something, which in my opinion is missing in the ASP MVC.

The standard pipeline of handling a request in ASP MVC starts with creating a controller with implementation of IControllerFactory. The default one, uses simply a controller constructor, passing none to it. Then controller is returned and its Controller.ActionInvoker is queried for a method/action matching the request. If none is found, an exception is thrown. After reading this paragraph it must be clear, that adding an action to a controller can be done also on the action invoker level.

The IActionInvoker interface provides not much space to move, since it has only one, bool method. If we take a look into the default implementation, ControllerActionInvoker, we can find an interesting method called: FindAction. The method returns something called ActionDescriptor and in the default implementation scans only the controller type in the search of the actions. But we can describe some static methods and return them during the search. To address it, I introduced an IActionProvider interface, which can be (almost) easily implemented.

To get the whole idea, take a look into GIST: https://gist.github.com/989733

As always, all needed types should be registered in the Windsor Container and resolved with it (in the current example, the only need which is to be resolved is IControllerFactory, or nothing if you register service location with the new feature from MVC 3).

Hope you like it. In the very next post, the final implementation of one of IActionProviders.

NHibernate EntityAwareModelBinder for ASP MVC

It’s time to provide some more features before getting deeper into detached actions for ASP MVC. The very first requirement is to have a nice model binder, which not only uses a container to resolve all the parameter types (my previous model binder), but also is intelligent enough to deal with an ORM of your choice. And mine is NHibernate.

Before getting the final snippet, a few assumptions has to be made:

  • No hierarchies are bound automatically. For sake of simplicity, we’re considering only simple entities with no derivations.
  • All the collections, which reflect one-to-many relationships, are bound in the inverse way. The one ending has its collection marked as inversed (there is a drop-down for the many ending, where the parent can be selected)

To provide you with a better way of viewing the code, I pushed the file to the gisthub and it can be located under: https://gist.github.com/984310. It’s good time to take a look into it.

As you can see, the binder does some pretty nice things:

  • It still uses container as the fallback for all the models. Using Windsor you’d better be sure to have all of them registered
  • If entity has its id passed, it uses session to get it; otherwise a new instance is created. It’s up to you to save it in your session

Maybe it addresses a few concerns, like handling entities and non entities in one binder, but it’d be easier to get the whole idea having one straight class without the whole projects.

This is my default model binder in my current project so far and it provides strong base for the detached actions mechanism, which will be covered in the very next entry.

Thoughts?

Composition vs derivation

Assume you’re writing some reports in your application. You’ve just created the third controller covering some kind of reporting and it seems to be, that all the three controllers have a very similar code, modulo type passed as the entity type to your NH ISession.QueryOver() or another data source. It seems that, if the method creating report base was generic, it could be used in all the cases. You want to extract it, make it clearer and to stop repeating yourself. What would you do?

Derivation
The very first thing is to extract method in each of the controllers. Now they seem almost the same. A place is needed where the method can be easily moved. How about a super type? Let’s create a controller, call it in a fashionable way, for instance: ReportControllerBase, and move the method in there. Now you can easily remove the methods in the deriving controllers. Yeah! It’s reusable, everyone writing his/her report can derive from the ReportControllerBase and use its methods to speed up his/her task.

Composition
The very first step is exactly the same: the extract method must be done, to see the common code. Once it’s done, you notice that the whole method has only a few dependencies which can be easily pushed to parameters, for instance: isession, the entity type passed to query, the value used in some complex where clause, etc. You change all the field and properties usages to parameters which allows this method to be static. You create a static method and turn it into an extension method of a session. The refactorization is done, you can easily call this method in all the controllers, by simply calling an extension onto a session.

What’s the difference and why composition should be preferred
If you use C# or Java you should always be aware of one limitation: you can derive from only one type. Spending this ‘once in a lifetime’ for a simple functionality extraction, for me – that’s the wrong way. Using composition, and deriving only when you truly see that one type is another type, that’s the right way to go. In the next post I’ll write about ASP MVC Detached Actions, a simple mechanism you can use, to derive your controllers only, when it is needed and delegating common actions, without it.

RenderAction in MVC

Recently I was debating with my friend about using RenderAction methods instead of rendering partial views. One could say, what the fuzz is all about. It’s all about simplicity. Rendering some part of your page with partial, makes you create big, fat model, passing its parts all around (for instance Model.SthForFirstPartial, Model.SthForSecondPartial). It can bring you to one model per one view or even action and this is baaaad.
You have an alternative: you can simply render actions results in you parent view using mentioned methods. Advantages:

  • only atomic values passed (for instance, post id to render its comments)
  • atomic actions (like: Comments, a list of comments) with results rendering not full-blow html, but parts of it (JSON is also applicable in here)

It seems, that this would be all, but it is not. Using NHibernate, my favourite ORM, and having it instantiated once per request (for Windsor fans: LifestyleType.PerWebRequest) I can easily fetch needed data in the parent action, loading it in a session first level cache. The child action then, will simply get data already fetched, having no problems with getting to many hits on your db.

I do like this paradigm.

For disassemblers
(the people, which overuse Reflector, or its free replacements, to read code), there’s a few lines of code, which passes the original HttpContext with all its Items (yeah, that’s the base for having LifestyleType.PerWebRequest working), an excerpt from ChildActionExtensions
class:

var httpContext = htmlHelper.ViewContext.HttpContext;
var context = new RequestContext(httpContext, data2); // whoa! I'll get my request items back!
var httpHandler = new ChildActionMvcHandler(context);
httpContext.get_Server().Execute(HttpHandlerUtil.WrapForServerExecute(httpHandler), textWriter, true);

ASP MVC Model binders

Recently I had to create a model for ASP MVC, which would be bound by the model binder and had its properties set according to the request. It’s the most common case you can imagine, but there was one ‘but’. The model, because of its nature had to have non-default constructor. It was only a few parameters but it broke the DefaultModelBinder, which simply couldn’t find all the needed values. My response was quite fast, specially having the controller factory implemented in the following way:

/// <summary>
/// The controller factory building up the controllers with the unity container.
/// </summary>
public class ControllerFactory : DefaultControllerFactory
{
    private readonly IUnityContainer _container;

    public ControllerFactory(IUnityContainer container)
    {
        _container = container;
    }

    protected override IController GetControllerInstance(RequestContext requestContext, 
        Type controllerType)
    {
        return (IController)_container.Resolve(controllerType, null);
    }
}

The very next step was to replace the default binder stored in ModelBinders.Binders.DefaultBinder with another, controller-based implementation:

/// <summary>
/// The model binder building up the model objects with the unity container.
/// </summary>
public class ModelBinder : DefaultModelBinder
{
    private readonly IUnityContainer _container;

    public ModelBinder(IUnityContainer container)
    {
        _container = container;
    }

    protected override object CreateModel(ControllerContext controllerContext, 
                                          ModelBindingContext bindingContext,
                                          Type modelType)
    {
        var type = modelType;
        if (modelType.IsGenericType)
        {
            var genericTypeDefinition = modelType.GetGenericTypeDefinition();
            if (genericTypeDefinition == typeof (IDictionary<,>))
            {
                type = typeof (Dictionary<,>).MakeGenericType(modelType.GetGenericArguments());
            }
            else if (((genericTypeDefinition == typeof (IEnumerable<>)) ||
                      (genericTypeDefinition == typeof (ICollection<>))) ||
                     (genericTypeDefinition == typeof (IList<>)))
            {
                type = typeof (List<>).MakeGenericType(modelType.GetGenericArguments());
            }
        }

        // in the base method: return Activator.CreateInstance(type);
        return _container.Resolve(type, null); 
    }
}

As you can compare, the method simply delegates creating model to the container. Having this binder set allowed passing models with non-default constructors, so the problem was solved:] After a while, I considered following case: if the type is constructed with a container, the controller can also be passed an object implementing an interface registered in container. Hence, if a method needs a NHibernate ISession, this can be expressed not only as a parameter in Controller constructor, but also as a method parameter. This paradigm creates controllers with no parameters needed in constructor (or only common parameters, used in all actions) and all the others passed as action parameters. The result is a method, which can be perfectly tested in an environment where the only smallest, needed set of dependencies is passed (no more constructors with not needed in the current method parameters). What do you think about it?

An example of a controller:

public class CarController : Controller
{
    private readonly ISession _session;
    private const int PageSize = 10;

    public HomeController(ISession session)
    {
        _session = session;
    }

    public ActionResult Rent(IUserService userService, Guid carId)
    {
        using (var tx = _session.BeginTransaction())
        {
            var car = _session.Load<Car>(carId);
            var user = userService.GetCurrentUser();

            car.RentBy(user);
            
            tx.Commit();
        }

        return View();
    }

    public ActionResult Index( int? pageNo)
    {
        var page = pageNo ?? 0;

        var cars = _session.CreateQuery("from Car")
            .SetFirstResult(page*PageSize)
            .SetMaxResults(PageSize)
            .Future<Car>();

        return View(cars);
    }
}