It has already been six months since ASP.NET MVC framework was released and well over a year since enthusiasts and early adopters started to actively use it for their projects. A significant amount of knowledge and field experience has been gathered from using this framework in various projects, from simple public-facing sites up to complex applications of all sorts. A vast amount of articles and blogs have been written that address the advantages and disadvantages of the brand new ASP.NET MVC framework and compare it with the current mainstream ASP.NET WebForms model which now seems to be in disfavor.

Among many online discussions on the topic there is a specific line of questions that are asked again with increasing regularity. People are considering the idea of migrating their existing code base from ASP.NET WebForms to ASP.NET MVC expecting to benefit from the many listed advantages of the later. These questions typically come from developers experienced in ASP.NET WebForms who have heard and read much about ASP.NET MVC but not gathered any experience with it yet.

In this analysis I will directly address that particular interest and will talk about migration from ASP.NET WebForms to ASP.NET MVC. Applications created with ASP.NET WebForms usually follow some specific design patterns and adopt similar architectural decisions. It may not always be an optimal course of action to directly migrate these architectural patterns to the new framework, but it will clearly show the difference of the new model and what challenges and efforts are to be expected with moving to the new framework. I will discuss each of those ASP.NET WebForms design patterns and show whether and how they can be transferred and implemented in the new framework. This will not be a beginner introduction to either framework, I expect the reader to have a good working knowledge of the ASP.NET WebForms model and have some reading understanding of the new ASP.NET MVC paradigm. At the end of the discussion you should have a better understanding of the differences of those two frameworks and what amount of changes, reengineering and learning curve you should expect if you decide to go along with migration of your projects from ASP.NET WebForms model to ASP.NET MVC framework. My discussion will in part be influenced by experience and observations made while working on a large enterprise-class web application developed with ASP.NET WebForms and operating as software-on-demand (software-as-a-service – SaaS).

1. Page concept

In ASP.NET WebForms the presentation layer is built around the concept of pages. A page is a markup entity that can be presented to the user. A page resides in an *.aspx file and can usually be reached on a separate URL containing the path to the respective *.aspx file. Pages are combined into a site by providing links pointing to other pages.

An ASP.NET MVC application is designed around the idea of resources and views. An URL provides an access point to a resource. When a resource is requested, the application would serve back a representation of this resource (view) as appropriate according to the application logic. Usually a view would be a web page (also in *.aspx format) although this is not a requirement. A resource can have a representation as a block of text, as an XML document, be in JSON format etc. A URL may have an arbitrary format, does not need to contain any extension (*.aspx, *.xml etc) and does not point to any physical file in the web server directory.

2. Page lifecycle

With ASP.NET WebForms pages are created in a series of steps which comprise the page lifecycle. First, page properties are set, then the server controls are created following restoring of their properties from viewstate and control state, after which event handlers are executed. These stages altogether contribute to the final result, an output page markup that is sent back to the user.

In ASP.NET MVC framework the concept of pages and their lifecycle has been eliminated. The presentation model relies on views which do not use server controls. Generation of a view would typically require two steps. A model object is prepared to hold the data needed to be in the view and then passed along to the view which takes the model as an input and outputs the needed data with the appropriate markup. Since server controls are not supported, there are no control properties to be set or control events to be processed. Code-behind although technically possible is not used by default. A view resides in a single *.aspx file which uses a combination of HTML elements and server tags (as in classic ASP) to produce the output.

3. Active server controls

One of the strong sides of the ASP.NET WebForms has been support for server controls. Server controls are primarily used to render UI elements from simple HTML equivalents to very complex UI blocks, for example, interactive data grids directly bound to a data source. Server controls are represented by classes which expose various properties that influence how the control is rendered. With the support of JavaScript and the postback mechanism, server controls can perform as active elements raising events as a reaction to user input. These events can be handled by the server side logic.

The ASP.NET MVC framework leaves the concept of server controls behind. Building UI implies working directly with HTML, CSS and JavaScript. Elements can be customized with the standard HTML attributes they support and further styled with the standard CSS properties. ASP.NET MVC offers a bunch of HTML helper methods that take a few parameters and then render the respective HTML elements to a string. They can be added to markup using server tags (<%= Html.TextBox (...) %> or <% Response.Write (Html.DropDownList (...)) %>). It is possible and advised to build one’s own set of HTML helpers to address specific data formats and appearance requirements. Implementing control events would require manual addition of JavaScript event handlers. However these events cannot be directly processed as server side events. To accomplish this, a JavaScript handler can be set to initiate a request to be handed by a dedicated control action. The method logic should react to the event and rebuild the view if it is supposed to imitate the standard postback scenario where the same page is returned after the event is handled.

4. Event-driven model and postback mechanism

The ASP.NET WebForms model was designed to allow development of web sites with the same paradigm that desktop applications follow. Before all, it means abstracting away the low level markup elements (HTML, CSS, JavaScript) into server controls which can be manipulated like Windows UI controls. Server controls expose various properties and raise events that can be handled in the server side code. The function is achieved by using JavaScript to catch the HTML elements events and initiate a POST request to the current URL. Hence the name of the technique – the postback mechanism. The information as to which control has raised an event along with the event arguments is serialized into a string representation and injected into the page (control state) before it is posted back. The server side deserializes this information and calls the appropriate event handlers in the server side code. After the processing is complete, the page is reconstructed (with reflection of the changes event handlers could have introduced) and then sent back to the user.

The ASP.NET MVC framework goes away from this model. The views are designed from standard HTML elements with the use of CSS and JavaScript where appropriate. In order to catch an event and perform some server side processing as a reaction to it, the following strategy can be used. A JavaScript handler can be added to an HTML element and set to perform a request to some URL. The request will be handled by a respective controller action. If it is desired to use the same action for events raised by several controls, each JavaScript event handler should distinguish itself by adding parameters to that URL. The controller action will perform the required server side processing of the event. Afterwards the controller action should rebuild the view model reflecting the changes in the input controls (by reading from the submitted form and updating the model) and then return the same view by supplying the updated model to it. This will effectively achieve the postback effect, though the events will be accepted by controller actions, which may of course dispatch the processing further to specific handler code depending on the element that raised the event.

5. Controls state persistence

The postback mechanism supported by ASP.NET WebForms has a convenient feature of persisting control properties between postbacks. When a server control event occurs, the handler code would normally only focus on processing the event ignoring the rest of the page composition. The postback implementation takes care of the control properties. Before a page is submitted, the controls state is serialized and added to the page (as a hidden field). Piggybacked to the page, the control state then travels to the server, where it gets restored and applied to the controls before the page is rendered and returned again.

With the ASP.NET MVC not having the postback mechanism to offer, the controls persistence has to be done manually, which is quite simple. A posted form would arrive to a controller action that handles the POST URL. The logic should read from the submitted form, create the view model and update its properties with the submitted values. The view will receive this model and render the markup supplying the elements with the latest values available on the posted page. Using the model binding mechanism which automatically initializes complex objects from the submitted form, the manual reading from the submitted form and updating the model properties can be omitted altogether thus transparently achieving the elements persistence.

6. Stateful operation

The ASP.NET WebForms model wraps underlying mechanisms into many abstractions which are brought to simplify and speed up development. One of those abstractions is adding the statefulnes to web applications which operate over the stateless HTTP protocol. Stateful operation is achieved via automatic persistence of UI control properties between the postbacks and by giving developers the means to persist their other data. A page in ASP.NET WebForms can have its viewstate which is basically a page-scope persistent storage. Developers can use the viewstate to put there data they need to persist between postbacks.

The ASP.NET MVC framework embraces the stateless web nature and suggests designing applications in a way to reflect this underlying foundation. With the idea of pages not present in the ASP.NET MVC framework, the concept of page-specific (or rather view-specific) storage is not supported. An application needs to manually read from the submitted form at each POST request and reinitialize the UI elements it wants to achieve persistence for. Automatic model binding can simplify the process. Another alternative is the TempData collection which can keep the data between two adjacent requests (of any type, either POST or GET or other). It is implemented using server session resources. The session state itself is still available if needed.

7. Caching data

One technique that the ASP.NET WebForms developers have widely adopted is the caching of data. When treating web applications as stateful, certain design techniques can be adopted from the desktop applications architecture. Some data can be retrieved from the database once and then kept close at hand so that the various parts of the application can quickly get to this data when needed. The caching pattern may vary depending on the usage scenario of the data. The smallest scope and the shortest lifetime of the data can be achieved with the viewstate which is a page-specific storage. Its implementation serializes the data and keeps it within the page markup. A server session state can provide session-long persistence for the data that will be available to multiple pages. Finally, one can simply use static variables to keep some data shared between multiple user sessions for the same web application. This storage survives for the duration of the application domain.

The mechanism of viewstate is not available to ASP.NET MVC applications. If needed this local persistence can be achieved with hidden fields added to the page or by using the short-life storage – the TempData collection which keeps the data between two consequent requests. TempData is however a server-side storage and therefore consumes server memory resources. The server session state can be used in the same way to achieve a session-long persistence. The option with static variables is available as well.

8. Active page areas (user controls)

One of the most powerful mechanisms that the ASP.NET WebForms model offers is the support for user controls. This can take the development to the next level since user-defined controls can represent complex and independent UI elements (even whole page areas). These UI elements are commonly known as widgets. What is more important is their ability to perform as active elements. User controls can raise events including custom user-defined events with custom parameters. With the timer support added by the Microsoft AJAX library, user controls can perform regular operations on their own accord, like updating their content, changing their appearance and even sending messages to other active elements to ask them to synchronously react to the changes in the other controls. This allows for very easy creation of highly interactive content-driven pages.

The simplicity of the ASP.NET MVC model with its rejection of abstraction of web protocols and standards goes at a price. Not being able to use active server controls makes implementation of this level of interactivity a complex and a challenging task. The ASP.NET MVC v.1 does not offer any support for this situation. The upcoming ASP.NET MVC v.2 release is not expected to bring this functionality on board either. In the numerous community feature requests this would-be functionality is often referred to as "subcontrollers" or "partial requests". Some support has been added in a community project MVC Contrib. Short of that, widgets have to be implemented manually. One option is to use JavaScript to pull the data to display. This option however does not perform well in terms of accessibility and SEO-friendliness. Another more practical approach is to reserve a place for widget data in each of the view models (better in some base model class) and from each view hosting the widget to forward this data to the HTML helper rendering the widget. Handling widget events however will require more effort. Every view hosting the widget must be expected to raise the widget events. Event handling can be done in a dedicated controller action (or multiple actions) accepting requests from a widget. This can be achieved either through a single widget-specific URL or through view-specific URLs which would then require multiple implementations of the event handlers. The responsible action method however must be able to reconstruct the view the request originated from, that is, all the views containing this widget. Certain steps and design decisions have to be performed to make this model scalable as the number of widgets and views grows with the project. Generally speaking, design of interactive pages and implementation of active UI elements with the ASP.NET MVC framework requires substantial amount of work to do.

9. Interactive page behavior (controls interoperation)

The object-oriented abstraction over web standards and protocols that the ASP.NET WebForms framework offers allows for very easy creation of interactive pages. Developers have been accustomed to having page elements raise events, to handling these events in server-side code and updating parts of the page by manipulating the other UI controls. The programming paradigm is very much similar to the event-driven model of desktop applications.

With the ASP.NET MVC framework this object-oriented convenience is not available. The conceptual interaction between view elements will involve some amount of programming and workarounds. Some simple manipulation can be done on the client-side with JavaScript. For server-side processing, HTML elements can be set to raise events and perform asynchronous requests with JavaScript. The controller action that will handle these requests should have the logic analyzing the event type and origin and performing the necessary work to update the corresponding view and its other elements. Normally it would require reconstructing a model, updating it with the submitted element states and values and then returning the view that would render the updated model. The implementation may somewhat resemble the code blocks for handling Windows events in applications developed from scratch without the use of the GUI libraries like MFC of WTL. For this type of processing it can be recommended to build a small framework wrapping the event handling and dispatching the execution to the supplied handler functions.

10. Separation of markup and logic (code-behind)

One big advancement the ASP.NET WebForms model made over the other web frameworks available when it came out was the clean separation of markup code and server-side logic. Prior to that, development of data-driven web pages required mixing markup elements with server side code directly in one file. This led to high complexity and reduced readability of the page code due to two different types of code woven together. The ASP.NET WebForms introduced a division into two coupled parts: the markup (*.aspx file) and its code behind (*.aspx.cs or *.aspx.vb). This allowed for development of clean code structure. The markup part represented the fixed markup while the code-behind logic could manipulate these markup elements in an object-oriented fashion.

The ASP.NET MVC seemingly takes a step back by rejecting the code behind. Views are represented by a single *.aspx file where markup tags are intermingled with the server-side code (using the server tags (<% %>) like in classic ASP). It is possible to activate code-behind support, but it won’t bring much since server controls are not supported and therefore the advantage of manipulating them in an object-oriented fashion is not available. One can however use code-behind if a view is mostly constructed programmatically using the Response.Write calls and HTML helper methods. With the abundance of those, switching to code-behind may result in a better structure and improved readability of the code.

11. Programmatic generation of markup

With ASP.NET WebForms, pages are generated programmatically. The static markup part (residing in the *.aspx file) is transformed into a control objects hierarchy, which can then be manipulated by the code-behind logic. After the processing is done, the controls hierarchy is rendered to the text output by calling the Render methods of the controls in cascade. The achieved result is then served back to the user. This model relies on active server controls capable of rendering their design and current state to an HTML representation.

With the object abstraction not available in the ASP.NET MVC framework, the construction of views is done in a single pass by rendering markup elements into the output stream. Static markup elements declared in a view are sent automatically into the output. In order to deal with complexity, HTML helper methods can be designed to render complex design parts. They can be rendered through using the Response.Write method or its server tags equivalent (<%= %>) to add the HTML helper output to the response stream. Another option lies with using the partial views (the name and implied usage scenario for the *.ascx files in the ASP.NET MVC terminology). They can be rendered by using the Html.RenderPartial method supplied by the ASP.NET MVC framework.

12. Databound controls

Server controls supported by the ASP.NET WebForms framework can represent quite complex and interactive UI parts. Databound controls is a good example of how server controls can leverage easy creation of dynamic interfaces. Databound controls can be set to work directly with a datasource to achieve their goal, such as presenting data to the user and letting them modify it. This allows for creation of reusable UI parts that can provide independent behavior with no regard to the page they are hosted on.

With ASP.NET MVC not supporting active server controls, development of independent databound UI elements requires noticeable programming effort and can normally be achieved only to a limited degree. Presentation of data can be done relatively easy. It would require providing the data necessary to display in such a control to each view that is expected to host the control. A typical way is to add the necessary data to a base model class in order to keep the retrieval of this data in one place. The control can be rendered through a HTML helper or a partial view while supplying it with the data available in the host view model. Implementing dynamic behavior however will require more effort and will not be a scalable solution. The user control can be set to perform an asynchronous request with JavaScript to react to user input. The event handling code should however not only be able to process the request but to return the same view with the UI elements states and values preserved. It can be done manually on a small scale, but for complex applications with such functionality requirements the most reasonable course of actions would be to implement a custom framework to catch events, dispatch processing to appropriate handlers and reinstate the view. This may not be an easy task and will certainly require some good design skills to accomplish.

13. Ignorance of underlying technology (HTML/CSS/JavaScript, HTTP)

When developing applications with ASP.NET WebForms, programmers enjoy benefits of a quite high abstraction level that hides the low level details of underlying technology. Developers ignore HTML markup elements, CSS styling, JavaScript functionality as well as HTTP status codes and response headers. Instead, they work with the highly abstracted server-side event-driven framework. They design pages with server controls and achieve their desired look by setting controls properties. Event-driven model along with the postback mechanism undertakes the functionality of sending user input to the server and reinstating input control values on page reloads. Interactivity and in-place page updates are achieved by using UpdatePanels provided by the AJAX framework. Finally, HTTP status codes and response headers are typically left to be handled by the framework or statically configured in the web server (IIS). This altogether effectively isolates developers from the underlying technology and allows for rapid application development (RAD).

ASP.NET MVC offers a different architectural concept but it does not provide that level of abstraction. Knowledge of underlying technology is required at every step. With the absence of server controls, views are designed directly with HTML elements, styled with CSS and enriched with interactivity through the usage of JavaScript. Processing user input and reinstating input elements values will require working directly with HTML forms. Some of the work can be leveraged onto somewhat higher level by using HTML helpers (both built-in as well as custom designed which is highly encouraged) and JavaScript libraries (for example, jQuery). Another option to simplify markup design and dynamic view generation is to use a different view engine. A view is then designed with the specific view engine syntax that will be expanded into simple HTML elements and element groups (which can be generated through a loop description). There are several alternative view engines available, here is a brief overview: ASP.NET MVC View Engine Comparison. Even with these assistance tools, working with HTML, CSS and JavaScript is unavoidable in order to design complex views and finally quality accessible sites. Understanding of HTTP status codes and response headers is needed in order to design compliant and SEO-aware sites. With ASP.NET MVC framework, an URL does not map to an *.aspx page any more but results in one or the other view to be returned. It is up to the application logic to decide whether an URL is valid and return an appropriate HTTP status code along with the needed response headers properly set.

14. URL parameters

With the ASP.NET WebForms framework missing an URL rewriting engine, developers usually stick with the default functionality available. That means URLs always point to an *.aspx page and communicate the needed arguments via URL parameters. A typical ASP.NET WebForms URL would look like this:

http://www.samplesite.com/Articles.aspx?User=5&Category=14

The parameters are then extracted in the code-behind of the page and used in the page logic.

With the ASP.NET MVC framework designed around views but not pages the composition of URLs is completely different. This same URL with parameters would now be designed in the following fashion:

http://www.samplesite.com/users/5/aticles/categories/14

Or in a way more preferable for SEO (Search Engine Optimization):

http://www.samplesite.com/users/code-monkey/aticles/categories/databases

In ASP.NET MVC terminology, URLs are referred to as routes. A route points to a resource or its specific representation. The route map defined within an ASP.NET MVC application should contain a record for this route so that the framework can recognize it at run-time and dispatch the incoming request to the appropriate controller action which will handle the request. Parts of the route can be marked as variable parameters restricted by constraints specified via regular expressions. This way, a family of similar URLs would trigger the same controller action which will receive the route variables as parameters.

It is possible to emulate the look of old-style URLs by defining the appropriate route format. This would mostly make sense for backward compatibility. Newly designed applications should follow the model of parameterless routes to embrace the RESTful architecture.

The above discussion considered the typical ASP.NET WebForms design patterns in the context of their possible migration to the ASP.NET MVC framework. Some of the concepts can easily be reengineered in ASP.NET MVC. The others will present a real challenge to recreate. Some would simply not be applicable. For now the biggest downside of the ASP.NET MVC framework is its missing support for active independent page parts (known as user controls or widgets). It would require usage of JavaScript and some amount of trickery to create pages with that level of interactivity and dynamism. For complex applications to support this on a bigger scale, it would be advisable to consider building an own framework for handling client-side asynchronous events. In some sense, it would mean recreation of parts of functionality offered by the ASP.NET WebForms framework which may be seen as reinventing the wheel. All pros and cons have to be considered when deciding which framework to use for a next project. The same considerations apply when making a decision to migrate an existing project from ASP.NET WebForms to ASP.NET MVC.