Last time we began comparing ASP.NET Web Forms with ASP.NET MVC. We examined the strengths of Web Forms. This time we will start by taking a close look at its weaknesses. This is the second part of a four-part series.
Contributed by Xianzhong Zhu Rating: / 7 November 11, 2008
On the whole, the weakness of the traditional ASP.NET Web Forms solution mainly lies in the following four aspects. Let's check each of them one by one.
(1) ViewState and Postbacks
Maybe the most disputable point people often bring forward about ASP.NET Web Forms relates to ViewState and Postbacks. To introduce an event-driven approach and overcome the stateless nature (and also obstacle) of HTTP protocol to simulate the old Windows form model development experience, ASP.NET Web Forms introduces ViewState and Postback. The end result is both ViewState and Postbacks have caused lots of problems and increased the complexity of web application development. Even simple web pages can produce a ViewState larger than 100KB in size that heavily affects the performance of the application sometimes.
Is ViewState is a must have in an ASP.NET application? In fact, most existing web pages usually feature a good many hyperlinks. When you click one of the links, you will be navigated to a new page. Since clicking the links will lead you to another page, what is the use of ViewState within the page? In practice, when I start to write a new web project, the first thing I do is turn off the enableViewState (and sometimes enableSessionState) parameter from inside the Web.config file.
Some may ask me what sense there is to using Web Forms since I turn off ViewState. My answer is: there are many reasons. Web Form provides a control model, and so users can take advantage of the easy-to-grasp mode to set/get the value of a text box, and also, they can use many button events easily to write related event handlers to trigger various business logics. Moreover, using Web Forms is simple and clear.
Well, without ViewState why can you use the events of the controls? Of course, you can if the events are not complex ones. Here is an example. The TextBox's TextChange event belongs to complex events, as well as the Command event of the GridView control. However, the click event of a Button control is the "simple event."
As with the event, there are also complex states and simple ones. Take, again, for example: the state of each sub-control within each line inside the GridView control is a "complex state," while the Text property of a TextBox control belongs to a "simple state." "Complex states" and "complex events" require ViewState, while the simple ones do not. So, why not try to use simple states and events instead of complex ones?
One of the most prominent and significant features of ASP.NET Web Forms lies in its powerful (and complex) component model. Inside this model was introduced something named "page life cycle." Many people threw stones at it and accused it of killing system performance. In essence, this complex life-cycle does, at some times, run without any efficient result again and again. However, assuming that the ASP.NET "page life cycle" kills performance is not right.
Suppose that you put 1,000 to 10,000 button controls on an .aspx page. I pledge that the application runs quickly. In real environments, what leads to low efficiency lies in many aspects: the database access solution, the buffer mechanism, asynchronous invocation, the web server related payload balance, and so forth. These factors need to be carefully taken into consideration.
In constructing large ASP.NET Web Forms-based projects, you might find great difficulty in controlling the rendering of the HTML contents. ASP.NET server controls often render HTML with mixed inline style and deprecated tags that do not follow web standards.
ASP.NET Web Forms provide people plenty of controls; third parties have added many. The various server controls possess strong functionalities and are easy to use. As you may have seen, in most Microsoft techniques-related speeches, the GridView is usually used. With a drag and some clicks, it can be easily bound to a DataSet (or many other ADO.NET items). So a data table is generated, with easy editing, deleting support, and easy event responses.
Regrettably, there are many defects with the GridView control. If you want to use the advanced functionalities, such as appending, editing, and deleting, of the GridView control, ViewState becomes a MUST HAVE.
Now, what we care about is the HTML content generated from the GridView control.
Let's look at a related example. The following shows you some simple GridView control-related HTML code:
<td><a href="javascript:__doPostBack('GridView1','Select$6')" style="color:#8C4510;">Select</a></td><td>7</td><td>Produce</td><td>Dried fruit and bean curd</td>
<td><a href="javascript:__doPostBack('GridView1','Select$7')" style="color:#8C4510;">Select</a></td><td>8</td><td>Seafood</td><td>Seaweed and fish</td>
As you can see above, GridView generates a <table /> element with many ugly items in it. It's pretty difficult to control the style of the table. Although GridView provides detailed style definition from the title to each cell, there is far less flexibility. And also, the GridView control-generated HTML tags do not correspond to Web standards (e.g. cannot generate the <th/> tag).
So, in this sense, we can complain about Web Forms, while at the same time we advocate rejecting the GridView-like complex controls (including DataList, FormView, etc.). Then a question arises: when GridView is rejected, what's the sense of still using Web Forms?
In fact, the ViewState, Postback, and GridView are not all of Web Forms. In my opinion, the Control model (or the Component model) really represents the key part of Web Forms. As you may know, the infrastructure of this model is absolutely excellent. Now I will show you some related examples (although they are very elementary).
First, let's take a look at the commonly-used DemoControl.ascx user control:
<%@ Control Language="C#" AutoEventWireup="true" %>
When you launch the above page in a browser and view the related page source, you will get the following:
<div>
Hello World!
</div>
How clean the above code is!
Another example is Master Page: its <asp:ContentPlaceHolder /> will not generate any redundant code. This proves an important fact that a web form based upon user controls will not produce useless and nasty code. Besides this, most of the fundamental controls, such as TextBox, CheckBox (not setting Text property), Panel, etc. will not produce useless code at all.
So, where on earth did the above-mentioned "nasty" tags come from? As you may have guessed, they all resulted from complex server controls, such as GridView, FormView, and many Data controls. However, there is an exception among these complex controls-Repeater. The following gives an example of the Repeater control:
When you watch the resulting HTML tags rendered on the browser side (herein we omit it), you will find there is also clean code generated for the Repeater control without even a line of useless code.
With the release of ASP.NET 3.5, a new and powerful server control comes to you-ListView. Nowadays, you can easily find many examples related to this control, so we won't dwell on it here. However, there is an important point that deserves to be emphasized: as with the Repeater control, ListView will lead to clean HTML marks, and you can manipulate its HTML contents all by yourself.
To try to avoid using the GridView, DataList, and FormView. I highly recommend that you use Repeater and ListView as many as possible.
Another problem with Web Forms is the integration of JavaScript frameworks due to the naming conventions of rendered HTML. The page life cycle of the Web Form is too complex and features tight coupling between everything in the ASP.NET framework; furthermore, a single class is used both to display output and handle user input. So unit testing is an almost impossible task. However, today unit testing is very important in modern software development, especially when we follow agile methodologies and practices. Since the web is a stateless thing, Events, Postbacks and ViewState are not a good way to go.
As I've mentioned above, we can use Web Forms to freely control the HTML attributes and styles on the page. However, there is no doubt that we have no way (short of "hacking") to let the Web controls generate a simple ID. Here, let's take a TextBox control for example: although we specified its server side ID as txtUserName, the final client side ID might be LoginForm_txtUserName because it's within a NamingContainer whose ID is "LoginForm."
With the appearance of the component model, there also arises tons of controls. We know that one of the main purposes of controls is multi-use, which in turn requires high cohesion that does not rest upon outside factors as much as possible. Therefore, to generate a unique ID on the client side for the related server side control, Web Forms introduces a new concept-NamingContainer. Server controls inside a NamingContainer will result in a client-side ID prefixed with the NamingContainer-provided rules. In this way, the client-side ID can be made unique.
Another typical example relates to AJAX, a JavaScript technique implemented on the browser side. In AJAX-associated programming, we usually work with various DOM elements using JavaScript. In a non-Web Forms page, we can write something like the following:
However, due to the NamingContainer, when we use Web Forms-related server controls, it might be impossible to locate the textbox element (the result <input />) through the TextBox server control. To overcome this problem, the server control model introduces a ClientID property through which we can acquire the client-side ID on the server side. For example, if you put the above code inside a user control, you should write it like this:
<%@ Control Language="C#" AutoEventWireup="true" %>
Please take notice of the name and id property of the above <input /> element here, all of which are in relation to marks left by NamingContainer. However, because we've used the <%= %> mark on the page to directly control the ID property of the server control, we can access the corresponding <input /> element related to the server side TextBox control using client-side JavaScript.
As you've seen above, this kind of peculiar client-side ID is difficult to forecast in the design; it is just the so-called "client-side ID pollution" caused by using Web Forms.
The above JavaScript code is aimed at adding 1 to a counter every 500 ms, and showing the value of the counter at the TextBox control. However, in a large and complex project, with the JavaScript code on the pages getting more and more complex, we'd better transfer the scripts to individual .js files and refer to them in the pages. As is well known, using individual .js files facilitates code management and improves performance.
If you put the JavaScript code directly on the pages, every time the page is loaded, it will need to download these JavaScript codes. The .js files can be buffered, so that they only need to load one time. The script files can be utilized again and again, which decreases the communication between the client side and the server side so that loading speed is increased and performance is improved.
Now here is the issue. To correctly refer to the DOM element generated by the Server Control at the page, we have to use the <%= %> mark to output the property 为 ClientID. However, the <%= %> mark can not be used inside the .js file! This example represents another kind of "client-side ID pollution" caused by using WebForms.
So, what should we do with the above puzzle? The answer is to only extract the invariable parts into .js files while leaving the variable parts (such as the client-side ID of the server control) on the page. Also, another typical solution to this is to use the Component technique, a good example of which is the ASP.NET AJAX Control Toolkit Extenders. For brevity, I won't list related code examples; you can check these out yourself.
Over a period of time, the Rails framework has become popular, especially with the combination known as Ruby On Rails. So, within the .NET community there also appeared a Monorail, and the voices criticizing Web Forms have become louder and louder. With Microsoft itself producing the new ASP.NET MVC framework, Web Forms critics become even more critical. Well, will Web Forms quit the stage and become obsolete? Let's look more closely into the ASP.NET MVC framework and find out the answer.
Before making comments on ASP.NET MVC architecture, it's necessary to say a few words about it. We will begin to cover it in the next part of this four-part series.