Well, right up until this morning I was planning on blogging about the similarities and differences between the patterns used by the Web Client Software Factory (WCSF) and the up and coming ASP.NET MVC Framework... and then I saw Glenn’s post linking to this great article on patterns used to structure User Interface code. Gutted. Someone has already done it, and what’s worse, they’ve done it much better and more thoroughly than what I had in mind!
Still, I think I can squeeze some mileage out of my thoughts over the past few days... J
Much of this post is my current evolving thinking on the two frameworks, and therefore if you disagree do feel free to chip in and air your views. I’m only specifically comparing against the WCSF because I feel they share many characteristics and address similar problem spaces, and so I think it leads to a good illustration of what the MVC framework might give us, and what you need to be aware of.
My thoughts are also based entirely on what information is in the public domain – I have not had any internal conversations about this, so not only does it “not necessarily represent the views of my employer”, but chances are it will be just plain wrong as CTPs start to appear... so join the debate!
In case you are not sure which patterns I’m referring to, have a quick read of the links under patterns used in the Web Client Software Factory. Specifically we’re interested in View-Presenter and Application Controller. For the MVC framework, there is an hour long video of Scott doing a demo, two posts by Scott here and here, and a good set of notes here.
So how do these WCSF patterns directly compare to those proposed in the ASP.NET Model-View-Controller framework? In the Web Client factory we have a Model (implied, although not named in View-Presenter), a View, a Presenter, and a Controller, and in the MVC framework we have a Model, View, and Controller. So surely the mapping is pretty obvious? Well, it isn’t the simple one-to-one you might think. Here’s what I’ve come up with so far;
Interaction with Business logic
View (code behind)*
* Two points to note; a) you don’t necessarily have to split a View by code behind & mark-up in the MVC framework, but it seems a logical way to indicate the two roles a page can fulfil; b) many people use the Controller as a facade to the business logic in the WCSF, but the key above is that the instruction to interact with the logic is generally initiated by the Presenter calling a method on the Controller.
So what are these key differences? I’ll try to boil it down to some concrete points.
The WCSF tends to have an Application Controller per module, but the MVC framework has many (likely to be one per group of views). So in the WCSF we might have a SalesController that handles all page flow (and potentially business logic interaction) for the Sales module. However, in the MVC framework we might have a PricingController, an InvoiceController, and a CustomerController. Page flow is not necessarily owned by any single Controller.
There may therefore be an opportunity in MVC framework applications to use something similar to an Application Controller to centralise some of the page flow; perhaps by directing all relevant requests to a single Controller Action on an Application Controller to route appropriately. More thought required I reckon!
The primary entry point to the WCSF framework is the View followed by the Presenter. So when the user browses to “~/DisplayProducts.aspx”, the DisplayProducts page is constructed, and the DisplayProductsPresenter is attached to it. This Presenter then drives interaction with the Controller as required to fetch Model data, decide on Page Flow, and so on.
In the MVC framework, the primary entry point is a Controller, as Controllers are URL addressable. So when the user browses to “~/Products/Display”, the ProductsController would be created, and it’s “Display” action would be invoked. This then interacts with the Model and decides which View to use to render the output.
This also drives the relationship between Views and Controllers; rather than there being one Controller for a set of Views (as I approximated above) it is really that an area of functionality has a single Controller – and that Controller may have a set of supporting Views. Therefore the Controller becomes the primary unit driving application functionality, contrary to the WCSF, in which Views are the primary unit that drives functionality.
Of course, the more obvious point to note on Entry Points is the REST-friendly URLs that the MVC framework uses by default. I don’t personally think this adds any significant benefits, but it certainly looks clean and sits with the framework well.
The MVC framework has no separation of View and Presenter. The WCSF splits presentation logic into a Presenter class, and the technology-specific implementation of this into an ASPX page that implements the View definition. Conversely, in the MVC framework all logic to co-ordinate the physical rendering of a result set is contained in an ASPX page.
Perhaps an interesting point here is that the MVC framework’s Controller actually does much of the work that the WCSF’s Presenter does (in initiating interaction with the Model), and therefore MVC framework Views are expected to be significantly simpler than the View-Presenter pairing in the WCSF – pretty much just rendering mark-up and data binding expressions. This simple presentation code is roughly equivalent to what is contained in the WCSF’s View implementation (without the Presenter). So is there any point in separating further “presentation logic” in the MVC framework?
There are two reasons why a Presenter is useful in my opinion;
a) When there is real logic required to decide how to render a View.
b) When this real logic would benefit from Unit Testing.
But the approach encouraged by the MVC framework is to avoid logic in a view, and to stick to pretty straightforward data-binding etc. Instead of one complex View, you may choose to have many simpler Views. For example, if you have a list of products that can be clicked to display details of each, in the WCSF you may implement this as a single View with collapsible sections... hence there is logic to handle clicks, showing and hiding sections, retrieving data, and so on. However, in the MVC framework this would possibly be better implemented as two Views – a list View, and a details View. When the list is clicked, the request goes through to the Controller which renders the result using the details View. This is in fact likely to be necessary to avoid the View from interacting with the Model. (How does it get the individual product’s details if a View can’t interact directly with the Model? It can’t! It needs the Controller to do that first.)
Something not so obvious is the way in which each framework sits in the ASP.NET runtime. Scott points out the following in this post about the MVC framework;
The MVC framework supports using the existing ASP.NET .ASPX, .ASCX, and .Master markup files as "view templates" (meaning you can easily use existing ASP.NET features like nested master pages, <%= %> snippets, declarative server controls, templates, data-binding, localization, etc). It does not, however, use the existing post-back model for interactions back to the server. Instead, you'll route all end-user interactions to a Controller class instead - which helps ensure clean separation of concerns and testability (it also means no viewstate or page lifecycle with MVC based views).
In other words, the choice to force all requests through the Controller outlaws the post-back model. In contrast, one of the goals of the WCSF was to support standard ASP.NET functionality wherever possible, to maximise the speed at which developers could get going with it, and allow it to sit well with existing frameworks. This is of course because the WCSF is an accelerator built on the framework, and the MVC framework is just that... an underlying framework.
The choice not to support post-backs in the MVC framework makes absolute sense to produce a more purist application architecture, but it does mean that developers must shift how they think about writing aspx pages.
I’ve mentioned this in a discussion about the patterns because I think it helps define component responsibilities – i.e. a View is much more lightweight in the MVC framework than a classic ASPX page might be. It moves the focus away from building WinForms-like pages to building simple rendering-only templates. I personally believe that if you make this leap, you’re more likely to avoid building monstrous pages that rely heavily on View State, and are difficult to test and maintain...
I also wonder what kind of benefits we may see by not using View State, not going through a page initialisation and load for every post-back button click...
To conclude, then, my view is that these two frameworks share some common objectives and techniques, and therefore that each can potentially contribute significantly to the other. In the comments on his posts Scott implies a CTP is just around the corner, so let’s look forward to playing with it for real.