Having just completed a relatively large project using the newly released ASP.Net MVC Framework, I thought this would be a good time to post my thoughts on the framework. I have to say that the bulk of my experience with MVC framework comes from my time using Ruby on Rails, so many of my perceptions will be coloured by this.
First of all, for anyone who isn’t familiar with MVC (or Model View Controller), it’s a design pattern that emphasises the separation of concerns within the application, essentially: presentation data is kept separate from the application data, which – in turn – is separated from the logic relating to data storage, manipulation and retrieval. The result is – for the most part – an application that is surprisingly easy to maintain and adapt.
The idea is to have a controller class, which exposes several public methods – or, actions – which can be called by a web request. These actions execute a task, often involving communication with data storage through the model layer, and then finally pass data to a view, which renders the data and returns that to the user. Some actions may have filters that run at various stages in the request, and can alter the end result of the request (a common example is to ensure a user is authenticated before processing an action).
For the most part, I have been pleased with the ASP.Net MVC Framework. It bears striking resemblances in many places to Ruby on Rails, however it is often apparent that the framework is in its early stages as it is not as polished as Ruby on Rails.
Filters were one thing that irritated me somewhat, however they also had some features that I thought were original. First, I thought that the usage of filters was cumbersome and quite inelegant: filters can be placed either on an action or an all actions in a controller class by decorating the method or class with the appropriate filter attribute. The result of this method is that your controllers can become a hodgepodge of filter attributes. I wish I had the syntactic sugar of Ruby on Rails’ before_filter function, where it’s possible to write:
before_filter :require_admin, :only => [:delete, :create, :edit]
before_filter :require_logged_in, :except => [:login, :register]
I think that something based on the above would be a much neater way of specifying filters.
I liked having access to the “request context” from all the main parts of the application. It serves as a rather straight-forward method of passing data between the layers and of accessing the original request information. Something that can be difficult to do when you get deep into Rails applications: you lose the context of the request; you can’t get the original controller action or other request data.
I thought that the approach of using the ActionResult type to offload the work of processing each type of result was an excellent idea. It actually neatly avoids a common source of errors encountered during the development or Rails applications: the “double render” error. This error happens when, for example, a redirect is issued but then the controller continues to issue a view result also (caused because Ruby on Rails controller functions responsible for issuing results do not cause the controller action to return). Returning the ActionResult neatly avoids that issue.
Initially I took great issue with the typical method of passing data into views via the ViewData dictionary. I didn’t like the lack of strong-typing, the messiness this introduced into the view code, nor the ease with which certain things could be omitted from the dictionary. I’m aware that the first and last really also apply to Ruby on Rails: the first I can ignore because Ruby, unlike C#, is dynamically typed; the second however, remains equally valid. I would like to have some sort of contract between the View and the Controller that specified what data will be supplied, although I’m aware this is heading more toward the MCP design pattern.
Shortly after my disappointment over the ViewData dictionary, I discovered the existence of page models. The ASP.Net MVC framework allows you to create strongly typed views by use of a page model (in most cases, a class that exposes a number of properties containing information that would normally be passed via the ViewData. It doesn’t allow you to require values to be passed into the view, but it’s much better than the alternative.
Then finally we have the Model Binding of the ASP.Net Framework. This is still a bit of a black art to me; I’ve not yet had time to sufficiently examine its workings, but it is rather nifty. It enables the binding of values to objects in the controller and views; this allows controller actions to use model objects (e.g. a user object) as a parameter rather than having a parameter for each field of the user. It also allows “sticky fields” to be implemented very easily in the View.
That’s all that’s come to mind right now – although I’m certainly sure there are other things that I’ve overlooked. You may notice that I’ve omitted practically any reference to the Model part of MVC; this isn’t a co-incidence, it’s an avenue that I’m leaving open to the possibility of future posts given the fact that the ASP.Net MVC framework does not tie you to one particular ORM like Ruby on Rails does (generally speaking). It would make the scope of the post far too large, and I feel that this post is pushing the bounds of length regardless.
Anyway, these are my thoughts; if anyone has some other views, contributions or corrections, I look forward to reading them in the comments.