I seen and written a lot of web forms code over the years. It seems to me that there are basically four different forms that the code can take:
- Classic ASP
- Model View Presenter
In this post we will look at how you can recognize each one and discuss the advantages and disadvantages of each style.
Before ASP.net there was classic ASP. At that time technologies like server side includes and cgi scripts were all the rage. The content of the web page is written with minimal help of any sort of domain specific language.
If you encounter an ASP.net application written in this style you’ll see a lot of calls to Response.Write. This call writes directly to the output stream that is being sent to the browser.
For example in BugTracker.net there are some code blocks that look like
Here a number of variables are written out directly to the output stream. In this case the writing out is embedded in some HTML markup.
This style can be quite performant as there is very little overhead to writing to the response stream. It is also quite easy for maintenance developers to understand what is going on.
It is, however, difficult to provide any sort of structure to applications written in this style. Should a component in the middle of the page need to change some earlier part of the page then it is almost impossible. You have to write to some buffer and then rewrite the existing content. The code quickly turns into a spaghetti mess. You also end up writing out complex escape sequences just to get the actual markdown you want. For instance in this example code also taken from BugTracker.NET:
There is need to escape the quotation marks and also to escape new line characters – something I don’t really understand.
While performant the complexity of building an intricate application using this style requires a great deal of care. I would recommend against using this style due to the potential to create a terrible mess.
If you happen to have an application that uses this style then a good trick to migrate away from it is to simply start by replacing the Response.Write with the language provided for you: the aspx domain specific language.
In the case of the above code we could quite easily replace it with inline code:
While writing this version of the code I came across a number of bugs and fixed them. Most of the issues were related to incorrect tag termination. The domain specific language that is a mixture of C# and HTML makes issues far more apparent and the code easier to read.
Code of this sort will probably date to the early days of ASP.net. Developers coming over from CGI approaches to web programming or even those coming from structured languages such as C are most likely to use this style.
In the late 90s and early 2000s Microsoft had a problem: their strategy called for moving to web development but very few of their existing developers had any experience doing web development. Most of their developers had experience with Visual Basic 6 which provided a drag and drop method of building applications out of a series of controls. These controls had event listeners attached to them that were where the majority of the programming occurred.
In order to allow developers to use their existing skills Microsoft developed WebForms which brought much of the same programming paradigm to the web. Controls can be paced onto the page and the event handlers execute on the server side. Custom controls can be built to provide reusable functionality between pages.
Very little of BugTracker.net is written using this style. One section that uses it is the log management screen, manage_logs.aspx.
Here you can see the famous runat="server" which is what tells ASP.net that this is a control that it should manage.
To this day this is probably the most common method of building web forms application. Huge numbers of vendor controls exist that follow this model. If you need a chart or a tree or a drop down box there are vendors anxious to sell you on that.
I’ve never been a huge fan of this approach. It is difficult to test and blurs any lines between presentation code and application logic. It is also contrary to how the web is supposed to work: state is stored on the server, the POST verb is used even when GET is more appropriate.
That being said there are tens of millions of very successful web sites that are written using this style. An application written in this style is not, on its own, a reason to replace an application.
Model View Presenter
Model View Presenter is one of the family of patterns I call MV-Something along with Model View Controller and Model View View-Model. It is a fairly well known pattern in the Microsoft world and is generally used to structure WPF and Silverlight applications. It is pretty rare to see this pattern in the wild with WebForms but if the original developers are from a Silverlight background.
Model View Presenter
In effect this style of developing web forms splits out the .aspx pages as views. The presenter is a class that governs the communication between the view and the model. It is what actually contains the application and contains the business logic. Finally the model is a simple plain old C#/VB object that contains no real logic.
I said that is is rare to see this in WebForms but there is a pretty popular project out there called Web Forms MVP that promotes this model. It is an additive framework (meaning you can adopt it as you go, one page at a time) that helps build testable, maintainable code.
Projects that use this structure properly are likely of higher quality than most Web Forms projects. If you happen to encounter a project that uses this structure it is advisable to continue using it.
The final style I’ve seen is the one that I have adopted when working with WebForms. I attempt to keep all the controller code in the code behind and all the display code in the view. In order to accomplish this I create protected properties on the code behind and use these to communicate with the aspx file.
A great example is creating a data grid. Using the WebForms method above one would create column definitions and then perform a data bind to attach some data source to the grid.
You can see there is a mixture, in the code behind, of controller and view logic. Not only does the code behind know how to get the data but also where to bind it. The latter should be the responsibility of the presentation or view layer.
Using the layered approach one would shift the display logic to the .aspx file.
As you can see this approach is somewhat more verbose than the pure WebForms approach. It also means that you can’t take advantage of most the controls you might typically use in a WebFroms application. For an experienced WebForms developer this would almost certainly slow you down. Adding sorting to a GridView is as easy as adding a sortable property to it. For my version you need to build an entire control yourself. There are, however, plenty of client side options that provide functionality similar to what is lost by doing away with WebForms. [Datatables](http://www.datatables.net/) is a jQuery based solution for grids and there are equivalent solutions for all other controls. The controls that are available are frequently lighter weight and more modern than the WebForms version.
We also totally abandon the event model in WebForms. This means that we don’t have to deal with post backs and view state. It does, however, put more logic in the Page_Load. In my mind this encourages smaller, simpler pages, which is A-Okay.
The second advantage I see is around readability. To me it is much easier to understand what is happening in the layered approach. There is less magic going on in the background much of which is unnecessary magic. Developers coming from other platforms such as PHP or even Rails will have an easy time understanding the code.
Finally keeping view logic away from the controller logic makes unit testing far easier. It is, of course, still difficult to test the monolithic HttpRequest and HttpResponse objects. Getting around that requires a much more dramatic change such as adopting OWIN. Because the view logic in the layered approach is split from the back end logic it is actually quite easy to move the code to ASP.net MVC. The example above might be changed by simply doing
Not only did I change this to MVC I also altered the view engine to Razor. We could drop the view into a Rails application with almost no changes as WebForms has an almost identical syntax to ERB/erubis.
Each of the styles has its advantages and disadvantages. Choosing the right solution is a matter of examining the tradeoffs within the context of your application and your team.