Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
Markdown Monster - The Markdown Editor for Windows

What's Ailing ASP.NET Web Forms


:P
On this page:

The recent announcement that ASP.NET will soon get an alternate engine in the ASP.NET Model View Controller framework (MVC - see last month’s editorial) has brought out some renewed discussion of the merits and shortcomings of Web Forms and the potential need for an alternate mechanism of building Web applications that provide a closer and purer model to raw Web development. This is true especially in light of the different development style that AJAX/Web 2.0 applications are introducing and some of the complications that it raises with the Web Forms development lifestyle.

 

The criticism that’s now slowly coming out is leveled mainly against the Web Forms engine that sits on top of the core ASP.NET Runtime. Much of the dissent regarding Web Forms comes from the ALT.NET end of the developer spectrum and especially from developers who are focusing on agile development, but there’s also a bit of grumbling from hard core ASP.NET developers in general who have hit some of the boundary conditions of the ASP.NET page model that Web Forms has introduced.  Web Forms are the most prominent feature of the ASP.NET engine. They provide an application model that abstracts away many of the Web’s stateless and HTML semantics and this somewhat leaky abstraction has both its strong sides and weaknesses.

Web Forms Strengths

 

Personally I’ve used Web Forms since Microsoft originally released .NET and I’ve been fairly content with this implementation. . Sure I’ve had a few problems and I’ve cursed certain features of Web Formsand I’ll get to those later on in this articlebut overall Web Forms have been a good model to work with over all those years. However, the discussion about potential alternate frameworks has also made me think a bit more about what works and what doesn’t  in Web Forms and what I want out of an alternate framework. So let me first list a few strengths and weaknesses of Web Forms from my perspective. I’ll start with the highlights of the good stuff.

 

Powerful, Scalable, Stable, and Mature

ASP.NET Web Forms have been around in production now for more than five years and they been have proven as a scalable and stable platform for building Web applications. Many high-end applications use ASP.NET and Web Forms to run high volume Web sites and ASP.NET has been nothing but stable in these environments. For me personally, ASP.NET has been extremely reliable compared to the COM-based environments I’ve been dealing with previously. ASP.NET and Web Forms have been rock solid for me for years with no major issues in scalability or stability in all these years of running all sorts of different applications both on my servers and for customer sites with applications large and small. I find it hard to put a value on the peace of mind this gives me.

 

Easy to Get Started With

ASP.NET is clearly an easy concept for developers to get started with because it automates a number of repetitive tasks for you. The PostBack model makes it easy to maintain POST data in controls without having to manually re-assign them on each and every POST operation. If you enable ViewState you can maintain non-POST data control state automatically. Microsoft designed the entire Visual Studio Web eco-system to provide an easy development experience with drag and drop functionality on a visual designer with property sheet support. Developers write code to respond to events, which provides a fairly straightforward model for hooking up application logic that feels natural if somewhat un-Web-like. This model provides a high level of abstraction that is great for getting started, but it’s also problematic because it separates the developer from the low level Web mechanics in many ways. I’ll come back to this flip side a little later.

 

Extensible, Extensible, Extensible

 

One of the main attractions of Web Forms is the rich control model that has resulted in a huge proliferation of custom controls from third parties that provide all sorts of additional functionality to ASP.NET. The control model is powerful, relatively easy to work with and provides a full eco-system from development experience to run-time capabilities and the ability to hook and extend the Web Form architecture at almost any point. This is also a strength and weakness in that thet Page framework APIs are very rich, but also very complex. Many of the classes in the framework (like Page) have huge interfaces and for more advanced scenarios you need to have an intimate familiarity with the Page event model. Becoming truly proficient with Web Forms beyond the basics can be a daunting task.

 

This is an  abbreviated list but I can’t stress enough all of what this short list encompasses – stability, scalability and flexibility with an established and stable API all of which are the cornerstones of a solid Web platform.

 

Concerns About Web Forms

 

If you’ve worked with Web Forms for a while and you’ve gotten reasonably proficient with the model, you’ve probably hit some of its limitations and quirks. Overall Web Forms work well, but I curse when I run into a few of these issues.

 

Web Forms and Leaky Abstraction

 

Web Forms provide an attractive platform for most developers, especially those coming from desktop development. Postback tracking, ViewState, event routing, and single-page metaphor are all based around a forms-based interface that resembles a Windows Forms style interface. The operative word here is resembles!

 

Criticism with ASP.NET’s Web Forms model comes mostly from hard core Web developers who see Web Forms as a leaky abstraction layer that doesn’t truly capture the Web paradigm. Web Forms essentially try to emulate a Windows Forms/desktop implementation that hides the stateless nature of the Web. Web Forms provide a high level of abstraction of the core Web implementation by using a sophisticated control and event-based engine that handles request routing, access, and rendering that mostly hides HTML and HTTP semantics from developers.

 

This is both a blessing and a curse. Web Forms allow developers to rapidly create applications simply by dragging and dropping controls and handling page-level events for both the page and the controls on the page. This works well, but it’s a high-level of abstraction and many developers completely forgetor never learnedhow the HTML layout actually works behind the scenes. As a result, it’s common to end up with non-validating HTML, or bloated and hard-to-manage HTML layout that is very designer unfriendly. Add to that a huge amount of ViewState if you don’t effectively manage ViewState properlyand you can easily end up with pages that are much bigger than they need to be and  slow as molasses.

 

One downside of the Web Forms framework is that behind this abstraction layer, Microsoft built a very complex engine that has many side effects in the Page pipeline. If you’ve ever built complex pages that contain many components on the page it can sometimes get very difficult to coordinate the event sequence for data binding, rendering, and setup of the various controls at the correct time in the page cycle. Do you load data in the Init, Load or PreRender events or do you assign values during postback events? Web Forms need to run through a single server-side form so they can’t easily be broken up into smaller logical units. In complex forms, event handlers can get very bulky with the tasks they need to handle and often in ways that can’t be easily refactored so you end up with code that is difficult to maintain and impossible to test.

 

I often run into scenarios such as how do Change events affect the binding and assignment process. When does one control initialize in relation to another is another common scenario. If you’ve built ASP.NET Web Forms applications of any complexity you have probably run into these sequencing problems more than a few times. These problems can bedevil even experienced ASP.NET developers, and downright infuriate new developers.

 

ViewState – The Evil Within

 

Personally, my biggest beef with Web Forms lies with ViewState. I hate ViewState and honestly I wish Microsoft would have never created it. In fact, I turn ViewState off in just about all of my Web Forms pages as a matter of initialization (but even then I can’t get away from it entirely). Why? Because ViewState bloats page content something fierce, has a bit of performance overhead (serialization), and in AJAX applications especially, ViewState corruption caused by client-side updates to Page data can be a royal pain to deal with.

 

I work with a variety of customers, see a fair amount of varying ASP.NET code, and I’m often called in to help diagnose performance problems with Web applications. In a large percentage of the cases, I find performance issues directly related to rampant use of ViewState and developers who don’t understand its impact on page size and performance.

 

The big problem with ViewState is that it’s non-deterministic and that control developers are encouraged to store all property state inside of ViewState, which is both inefficient and bloats the page content. There are ways around the issue. You can do as I do and turn off ViewState for any content that doesn’t need it—or more ambitiously on the entire page although that’s not always possible as some controls – especially third party ones – often can’t operate without ViewState. All of the stock ASP.NET controls that come in the box actually work with ViewState off although you may have to set a few additional properties explicitly and you may end up with a few extra code snippets to track certain settings, but you will generally end up with lighter and snappier pages that are also more AJAX friendly.

 

ViewState bloat mattered enough to me that I wrote a PreserveProperty Control (http://www.code-magazine.com/Article.aspx?quickid=0703051) that provides a more deterministic way of storing state content (either in ControlState, separate hidden variable, Cache or Session) which in my opinion would have been a much better way to provide page-level persistence. Rather than encouraging every property and sub control to be rooted in ViewState, a more deterministic approach would require more restraint and focus on the key aspects that need to be persisted rather than dumping everything into ViewState automatically.

Event Management Complexity

 

Web Forms are all about events. Page pipeline events, postback events, and change events all are at the core of Web Forms. While events are part of what makes Web Forms easy they can also make things complicated because ASP.NET fires a ton of events as part of each and every request. Figuring out exactly when each piece of code in your Page fires as well as when every control or user control fires takes a solid understanding of the full page model and control tree architecture which is not trivial and requires a bit of experience and time.

 

Another annoying overly helpful feature in Web Forms is the change event management. Raise your hand if you’ve ever struggled with ListBox SelectedValue issues where you needed to handle the actual SelectedIndexChanged event and you also need to assign the SelectedIndex property explicitly. Whenever change events are hooked up it’s very common to get unexpected behavior with these events firing from seemingly unrelated operations from control initialization and direct access.

 

This comes back to the specific implementation of the page framework and how and when events fire. Developers have to be intricately familiar with the event sequence which is no trivial matter since there are many, many events that fire as part of the page process both on the page and on each control.

 

Granted this is not one of the most frequent pain points, but they do happen and when they do happen they tend to be a huge time sink. I often find myself spending an inordinate amount of time experimenting around with different implementations as I move code back and forth between events only to end up removing the event code entirely and checking for a Request.Form variable for the button or postback event explicitly and then routing to a custom method instead. I end up cringing at the resultant messy and unmaintainable code I’ve just embedded into my application.

 

PostBacks

Web Forms are based on postbacks. Everything you do in a Web Forms page except the first page access tends to be a postback where the page always calls back and posts to the same page. Postbacks fired off anything but a button require some client-side JavaScript code that explicitly fires the PostBack event back to the same page and routes the request to a specific event. PostBack events are what makes the event-driven functionality of Web Forms possible, providing the WinForms-like eventing model that is both so easy to use and yet so  irksome to some.

 

The first and maybe most serious issue is that most postback operations are driven through JavaScript. For example, if you have a GridView on a page and you have the grid set up with paging enabled, each page change causes __doPostBack() client script to execute. Problem:  These JavaScript links are not search engine friendly since search engines will not follow JavaScript links. The same is true for LinkButtons, and AutoPostBack controls and just about all other servercontrols that support postback events. If browsers have JavaScript turned off (which is not as uncommon as you might think in some large organizations) your app also could be dead in the water if it can’t be navigated without these JavaScript postbacks.

 

If you want to trigger postbacks from the client side with JavaScript you have to generate the __doPostBack() calls on your own and there’s no easy way to generate the event signatures. The syntax for these callbacks is a bit cryptic and the links are generated through server-side code (GetPostBackEventReference()) that embeds control-specific information into the scriptcalls. It’s no fun trying to fire a client request like this dynamically from JavaScript writing unmaintainable code like this:

 

javascript:__doPostBack('ctl00$Content$dgItemList$ctl14$ctl01','')"

 

INamingContainer and ClientID Voodoo

 

The script code above is whacky mainly because of the long control id. Web Forms-generated client and unique IDs are a big problem when working with client-side AJAX code that needs to access a specific control. Web Forms generate ClientIDs based on containership which often results in very lengthy and cryptic control IDs that are difficult to reference from client script code. It’s always fun trying to reference a control ID like this from a simple control stored in a master page like this:

 

<input name="ctl00$Content$txtQty"

       type="text"

       value="1"

       id="ctl00_Content_txtQty" />

 

What do you do here if you need to use this control in client script? Reference the full cryptic ID which might change if you rename the container and then breaks your client code? Or use code like this:

 

var ctl = document.getElementById("<%= this.txtQty.ClientID %>");

 

which is ugly and unwieldy and won’t even work if you separate out your JavaScript code into a separate .js file. The long cryptic ids also are unfriendly to designers who often use CSS tags based on IDs (#controlId) to style layout.

 

AJAX and Web Forms

 

Client-side scripting and Web Forms in general don’t go together all that well. As I mentioned previously there are issues surrounding ViewState consistency if you use client script to update POST data sent back to the server. This makes it often difficult to work with frameworks other than ASP.NET AJAX, which is the only framework that explicitly understands the Web Form model and ViewState.

 

To me, Microsoft AJAX in general is not a great client-side library solution in the first place. It’s big, not very modular and provides only limited functionality for the client-side developer with the client framework being more of a core framework/reference implementation than a useful API library that provides usable functionality for client-side scripting. If you compare it to the lean and mean and highly functional approach of libraries like jQuery, Prototype, MooTools , and so on, Microsoft AJAX feels like it’s seriously lacking practical functionality. Add to that the rigidity and complexity of the control creation model and it’s hard to justify using Microsoft AJAX for anything but the server-side controls provided in UpdatePanel and the AJAX Toolkit controls.

 

Using alternative libraries with Web Forms is possible but there are some issues you need to watch out for. Specifically, ViewState corruption is a problem when updating client control content that is already stored in ViewState and then sending it back to the server. EventValidation as well can cause all sorts of problems with pages posting back to the server and you’ll want to likely turn this feature off on pages that use AJAX and modify control content.

 

Lack of Seperatation of Concerns

One of the big criticisms raised against Web Forms has been that it’s difficult to separate UI, controller, and business logic. With Web Forms it’s very easy —too easy maybe—to fall into the trap of putting all code into an ASPX page and its CodeBehind source code. The problem is that ASPX pages and the controls that are provided have so many ease of use and drag and drop features that just invite you to make bad architectural decisions, mixing your application and user interface logic in one place. While working this way is easy at first it often leads to very hard to maintain applications where hunting down logic issues can become a major Easter egg hunt.

 

That doesn’t mean that Web Forms automatically have to be badly designed. If you use business objects to handle all business-related operations and data access, you are already separating out the largest chunk of code using the Page’s CodeBehind only as a controller for the code. In addition, if you move most of your code out of the actual event handlers and create very specific and refactored methods that handle specific tasks in the page you can go a long way towards separation of concerns. The problem is that it requires strict restraint to actually do this because the Page model doesn’t encourage it in any way. But even if you do, it’s still difficult to separate your user interface and the controller code entirely because of the event-driven nature of the Page model, which often closely couples the view and page controller logic code. In effect, ASPX pages are mixing both the user interface and the controlling/driving code very closely rather than more explicitly separating the view from the processing logic. This is an important issue when testing is thrown into the mix.

 

No Support for Efficient Testing

 

Web Forms are difficult to unit test effectively. There are a number of reasons for this, primarily that there’s no good way to programmatically test ASPX pages and get effective feedback whether the page rendered properly. Sure you can run a HTTP-based test on pages, but the results out of those tests are not always conclusive as you are testing a high level non-code construct. HTTP-based testing also has a lot of overhead and can be very slow compared to direct assembly-level testing that is typically used with unit tests.

 

There’s also no effective way to directly instantiate a Web Forms Page class and Web Forms and ASP.NET don’t support interfaces on the intrinsic objects like Context, Request, Response, Session etc., that would allow easier implementation of mock objects for testing. Further, the event-driven interface model also makes it difficult to even devise effective tests for more complex pages, as page logic is often not isolated in single events/methods but spread over several events and methods. Also the surrounding page state may or may not be present in the test environment which further complicates matters. In short, Web Forms don’t lend themselves well to testing either as a whole or in isolation.

 

The Lack of the ASP.NET Cool Factor

 

Finally there’s growing concern that ASP.NET is losing its coolness factor. While a very subjective issue, the lack of coolseems to be the main reason that there are very few high profile, hip new public applications using ASP.NET these days. If you search around for Web applications that people are actively using today you will rarely find one that  is running an ASP.NET backend. You’ll be much more likely to find a PHP, Ruby or even Java backend, especially for new startups. ASP.NET has lost some of its progressive image over the years, especially with the agile crowd which seems to be driving most of the new wave of Web applications popping up on the Web today.

 

Part of the reason for this probably has to do with ASP.NET’s ties to the Windows platform which some perceive as more expensive to run on. But there’s also the perception that ASP.NET is a stodgy platform that’s used for business applications and not for more forward-thinking and progressive applications. I say perception here because I don’t think that this is actually a valid point—ASP.NET happens to be highly flexible platform and you can just about build any type of Web application on it without issues or concerns using either Web Forms or, if you’re so inclined,  by building an alternate framework that that provides a more specific platform. I’ve built a number of custom handler implementations that solved very specific business scenarios in a cleaner way than Web Forms do and the fact that this can be done effectively speaks well for the flexibility of the ASP.NET core engine.

Talking About ASP.NET MVC

 

One reason that this discussion of the adequacy of Web Forms has come to the forefront is that Microsoft has announced that they will release a new framework for ASP.NET based on the Model View Controller (MVC) pattern some time after the release of Visual Studio 2008, probably as part of SP1 for that product. Microsoft has aimed this framework at some of the shortcomings in Web Forms and to provide an alternative for developerswho are heavily into agile and test-driven development. MVC is not meant as a replacement for Web Forms but as an alternative— Microsoft will develop the two side-by-side.

 

It’s very, very early in the MVC Framework lifecycle, and at the time of this writing Microsoft has not even released a public preview of the technology although they’ve shown a number of public demos. The cornerstone of this new framework is that it provides clear separation of concerns and testability out of the box.

 

Microsoft implemented MVC as an alternate Http Handler framework so it’s not based on the Page class and bypasses a lot of the complexities of the Web Forms framework. One of the key features is the ability to create custom views that are responsible for rendering output for specific tasks. The controller is responsible for using the model to perform core application processing and then feeding result data to the view to render. It’s quite conceivable to build re-usable views for rendering RSS feeds or other XML output or a specific page display view like a login form or error page for example. By default, however, ASPX pages cane still beused  to render a view’s output using a ViewPage class. This class is based on the Page class, but it’s not called directly as an HTTP handler but rather just as a renderer from within the MVC engine which is still much more lightweight than running through the full page framework that a typical ASPX page runs through at runtime.

 

. One issue with this abbreviated Page cycle is that you cannot use any controls that require postbacks since the processing that provides the postback and ViewState mechanics are not part of MVC. I suspect that this default PageView will be a temporary holdover until Microsoft delivers a different and more tightly integrated control architecture for the MVC framework, but that’s just a guess at this point. In the meantime you can use the Page engine using ASP-style scripting (using <%= %> or <% %> server tags) as well as server controls for render-only operation. Many things like Master Pages, user controls and most render only controls work with this view. It’s possible to use controls like a Repeater or the new ListView for example, but some features for more advanced controls like the GridView like Paging or Sorting aren’t going to work because they rely on postbacks. This lets you apply some of your existing ASP.NET skillset, and save some time building some layouts without  creating HTML purely through ASP style script markup. Realize though by using things like MasterPages or user controls you may still incur some of the shortcomings like INamingContainer rendering funky control names and some loss of control over HTML rendering.

 

You can of course create a custom view that provides whatever rendering you’d like to implement from scratch and I’d wager that there will be many different view engines to choose from various third parties by the time the MVC framework releases.

 

MVC’s model works through URL routing to specific controller methods and any operation routes back to a specific method in the controller. Microsoft based the routing engine on a Ruby-like mechanism that parses clean URLs (like http://localhost/Customers/Show/1) and routes these URLs to specific controllers based on the URL scheme. The routing mechanism – like most things in the MVC framework – can be overridden easily so you can use different URL semantics to route a URL to a controller.

 

Controllers then use the model—which can be an explicit implementation as part of the project or a separate set of business objects—to access application-specific or business logic. The controller then manipulates the model to provide the result data that is rendered into the view.

Views are interface based and anything that implements the IView interface can act as a renderer and produce output. The interface is pretty basic with only a RenderView method that is passed a context and off you go to implement your own renderers. The beauty of this approach is that it will be possible to build very customized view renderers for things like plain data pages that are passed a an EntityRecord or a collection of objects for example, and the view can then decide to render this output. It brings a potentially more much more reusable mechanism for rendering output in a more generic way.

The MVC framework is quite a different way of building Web interfaces than Web Forms. It’s much more modular and the explicit separation of concerns means that code is scattered around a few source files. However, this separation makes it much easier to test the individual components of the Web application explicitly using your unit testing framework of choice.

 

Is MVC the Answer?

 

It’s interesting to hear this discussion given that Web Forms has been the darling of Web development on the .NET platform. In fact, I find it somewhat ironic to see that MVC is in some ways reverting back to more ASP classic-style ways of working with script-like HTML rendering and raw manual output, but with a much more strictly regimented approach to enforce methodology and code logic. I also remember the early days of ASP.NET when the ASP.NET Nazis were going around disdainfully condemning any use of script tags and inline script or assigning explicit URLs instead of using postbacks, yet some of those same folks undoubtedly are the ones welcoming MVC with open arms now. Ironic, ain’t it?

 

It’s too early to tell whether MVC will actually address the needs of most Web developers. Certainly from what’s been shown so far it looks like MVC will require a lot more code to build even simple pages. I’ve seen an early build of the framework and it’s not really clear to me how to effectively handle more complex pages without at some point getting mired into huge case statements to route code to decide which portion of the page needs updating. I have built several Web frameworks in the past that use a similar approach  to MVC and while you can easily do many simple things, in my experience this approach really starts falling apart when you have pages that contain many different and somewhat independent components. Managing this complexity through a controller-based approach that manages no state for you is much more difficult than what Web Forms provides today. We’ll have to wait and see how the framework shapes up and what patterns emerge to handle more complicated tasks. It probably helps to look at some of the Java or even some of the existing .NET frameworks that have been around for a while for doing MVC based Web development and compare notes.

But it’s early and there’s lots of opportunity for Microsoft (and the community) to come up with powerful view implementations that provide the best of what Web Forms had to offer and mix it with a more lightweight and low-level approach that MVC appears to be shooting for. The key, in my opinion, will be how well the View implementation compares to what Web Forms does today. The concepts of controllers and models are clear winners in my opinion, but the view architecture is going to be the determining factor of how well this technology will fare with the general developer community.

 

If nothing else I look forward to seeing how MVC will evolve and I think about opportunities to extend the framework. New frameworks always end up bringing new opportunities for doing things differently and MVC represents the process of a new framework evolving from a perspective where a lot of people are familiar with the underlying platform (ASP.NET) and can provide feedback and input to Microsoft. It ought to be an interesting journey.

 

On the other hand, I also think that it might well be a good time for Microsoft to explore a new development path since Web Forms have become somewhat stale at least from the perspective of Microsoft’s development for it. .NET 3.5 includes almost no new features in ASP.NET and beyond the introduction of Microsoft AJAX and hardly anything has changed in ASP.NET since the release of version 2.0. A new framework might throw a new spark into the development effort and also provide the community and third parties the ability to expand and build on top of a new platform. The potential is there, but it’s just too early to tell where things are headed.

 

In the meantime we’ll have to wait and see. For the moment I’m not quite ready to throw out the baby with the bathwater and put all of my hopes on a new unproven framework. There are a lot of good things going for Web Forms and just because Microsoft has decided to try something new doesn’t mean we all have to jump to it. After all, MVC frameworks have been around for some time and they haven’t made any significant inroads today. MVC will appeal to a specific set of developers immediately—for the rest of us, Microsoft will have to build a kick-ass framework to make it at least comparable in flexibility, extensibility, and usability as Web Forms. There are some interesting times ahead. I’ll be watching with interest…

Posted in ASP.NET  

The Voices of Reason


 

DotNetKicks.com
November 30, 2007

# What's Ailing ASP.NET Web Forms

You've been kicked (a good thing) - Trackback from DotNetKicks.com

Steve
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

That's an interesting post - it's good to get a perspective from someone who's worked with WebForms for so long.

For more views on migration from WebForms to MVC, see http://tinyurl.com/33b3t4

Regarding ASP.NET MVC being "new and unproven", notice that it's virtually a carbon copy of MonoRail which has been pretty solid in real-world use. Now Microsoft have officially given their blessing to this approach, we're likely to see a lot more uptake.

Manuel Abadia
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Rick,

You said:

"The big problem with ViewState is that it’s non-deterministic and that control developers are encouraged to store all property state inside of ViewState, which is both inefficient and bloats the page content."

IMHO most ViewState related problems came because of lack of knowledge of how the ViewState really works.

Read this carefully:

http://weblogs.asp.net/infinitiesloop/archive/2006/08/03/Truly-Understanding-Viewstate.aspx

And you will see what I mean.

Also, if you want to save the ViewState data that gets persisted to any other place, you can do it easily overriding SavePageStateToPersistenceMedium.

Bill Pierce
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Hey Rick,
Great post. My first jab is that the "concerns" seem to out weigh the "strengths" :)

I will echo Steve's comments RE: MonoRail and also throw in RoR as proving the real-world value of MVC.

You say "MVC will require a lot more code to build even simple pages". The same argument is made about writing unit tests, if I have to write more code, why is it better? I would also contend that MVC does not shine for simple sites, but for the complex sites where a repeater/datagrid/button just doesn't cut it. Also, how much development of "simple pages" do you do day-to-day? I also like to chide developers who complain about writing code :)

I use MonoRail for production applications and I am more productive than I ever was in .Net (which may simply mean I was a weak .Net developer :). I also do not want to write lines of repetitive code for generating Views, and I don't. Creating a textbox with two-way data-binding in MonoRail requires just as little code as it does in WebForms. I've also written complex pages with multiple unrelated components mixed with async requests/page updates. Never had to use a case statement or resort to Kludge# to pull it off.

The MonoRail and Rhino-Commons Subversion repositories have several low/medium complexity reference sites that you might want to checkout.

It appears to me that M$ is hoping that Silverlight will inject some "cool factor" back into ASP.Net development. It certainly is promising and we will have to wait and see.

-Bill

Bryan Watts
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

The ViewState property and the ViewState mechanism are often lumped together mistakenly, which causes a lot of anxiety in developers who don't understand otherwise.

The Control.ViewState property, where it is recommended you store all inter-request control state, is simply a dictionary which tracks a dirty bit on values. Implementing those values with a property whose name is the key is a nice trick for having the compiler ensure values mean the same thing across a control's inheritance hierarchy.

Dirty tracking is turned on after the Init phase. This means that any values set before the control has reached the Load phase, such as those set in markup, in the constructor, in a CreateChildControls() before being added, or during Init, aren't marked as dirty.

Here is the key: only values marked as dirty are serialized into the page's ViewState and persisted. This divides control state into "initial, static state" and "modified, dynamic state".

The static state (markup) is the definition of that a particular control instance. It is *always* that way and doesn't need to be persisted, so values aren't marked as dirty when initializing.

The dynamic state can change per-request. If a control's state changes after it is in the tree, that change needs to be represented the next time the tree is rebuilt (postback), and so it is marked as dirty and persisted.

When understood and used correctly, you only persist *exactly* as much data as is different from the initial state of the page. It is actually quite minimalist.

This also makes databinding slick. Bind on the first request and the page keeps its altered state from there. Load the data back up and rebind only if the user does something to warrant it.

With the right combination of databinding/viewstate and caching, it is theoretically possible to reach a state where non-postback requests don't hit the database.

Eric
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Nice essay Rick. It sums up a lot of the current strengths and weaknesses of ASP.NET Web Forms and also questions the future of ASP.NET MVC.

I wrote to ScottGu a while ago about the INamingContainer / "control ID mangling" issue and he said that a lot of people have expressed dissatisfaction with it. I got a ping back from a developer at Microsoft who said they were looking in to the issue. I don't see anything in ASP.NET 3.5, so I assume it did not get addressed at this point and time. I understand the need for a unique control ID when you have the potential for the same child control to exist multiple times on a page (using a repeater or grid or in different content sections), but I would like the ability to 'preserve' the client ID using an attribute on the control or on a parent control.

I've paid attention to all the new demos on ASP.NET MVC and it's very interesting to see the direction away from control markup and code-behind to inline code. Since the early days of perl CGI, ASP and PHP, I've embraced and accepted inline code. With a few helper methods to generate HTML inputs, you can create some pretty clean looking pages. The problem is they never seem to work in a designer (because the HTML is generated by function calls). With the advent of ASP.NET and it's server control markup, the designer was now usable. Personally, I rarely ever use the designer view and prefer inline code (even in ASP.NET). I've always felt the design view in VS.NET has slowed down the IDE and I avoid it, in favor of the code/markup window.

I'm optimistic about ASP.NET MVC, but I'm worried that Microsoft will again try to make it too RAD, 'drag and drop', 'look MA, no code!!!', etc...

Ben Mills
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

You mentioned that ASP.NET is seen as uncool and is not popular with the Agile crowd. My feeling is that these people are really passionate about great code and while ASP.NET is a great platform to write web applications, there are enough ugly points to make these developers look at other options. An example for me is the "INamingContainer and ClientID Voodoo" that you mentioned. The ID mangling drives me crazy. It forces me to write ugly Javascript and CSS. This point was brought up in a few blogs and (I believe) Scott Guthrie (General Manager within the Microsoft Developer Division) tried to say that it's better to use class names only and avoid IDs. In my mind this is just plain wrong and shows how Microsoft really don't understand the ways in which professional developers write HTML, CSS and Javascript - hence uncool.

Having said all that, ASP.NET is still my preferred web development platform. I just have to give up my aspirations of "perfect" HTML/CSS/Javascript. For the record, I've tried (and love) Ruby on Rails, but the hosting options are just awful compared to .NET hosting.

Finally, you mentioned testing and I'd like to point out the excellent Watir testing framework. It's really easy to write Ruby scripts to run UI tests in Internet Explorer. I have a script that navigates from the homepage to a product, adds the product to the cart and runs through the checkout. I run this test after every code deployment and I'm confident that my customers won't have any problems. That scripts is only around 50 lines of code.

Thanks for another great article. So many .NET authors seem unwilling to bring up the .NET warts.

Thanks,
Ben

Eric
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Bryan,

re: ViewState

Let's be honest... what percentage of ASP.NET developers have truly mastered ViewState?

I've read a number of articles on ViewState (some from this website) and have perused the internals using Reflector. I think I have a good understanding of how it works. That said, I can't think of that many places I'd actually want to enable it.

If it's an abstraction, that is that difficult to understand, and the underlying alternatives (read any basic PHP 101 book that teaches you how to use the GET/POST values and how to create hidden inputs) are much easier, you have to wonder what you're really gaining in the long run.

What situations do you advocate the benefits of ViewState?

-- Data Caching --

For large data sets (DataGrid, GridView, Repeater, etc) I would argue that it makes sense to cache this data in the Session or Application Cache instead and DataBind on each page load. This is how we did it in ASP.Classic, PHP, perl CGI, etc. Here I would argue that ViewState does more harm than good.

-- Event Model Abstraction --

While I really don't use the Control events that often, I think this is a decent use of ViewState (ControlState).

Checking to see if the text in a textbox has changed or if the selected list item in a dropdown has changed, we used to have to use hidden inputs to hold the 'previous value', and manually do the check ourselves (previous vs current = changed). Checking to see what button was pressed required minimal HTML attributes and server side code. That said, I think the web forms model abstracted these pretty well. The problem was the abuse of ViewState by other controls (like the DataGrid) that required the introduction of ControlState. The last time I checked (2.0 release) the dropdown list item changed event still required the use of ViewState (you could derive a new list and use ControlState to store the previous list index).

-- Replacement for Hidden Inputs --

That seems like an acceptable use of ViewState. As an added benefit you get encoding and protection via encryption.

-- Caching Property Values --

You elaborate a bit on this in your post. Most of the properties of WebControl derived controls are backed by ViewState. You outline the important concept of ViewState tracking, and the importance of when in the page lifecycle the control propety is set, but I've found that to most these are foreign concepts to your average ASP.NET developer.

For example, if you set Label1.ForeColor = Color.Red in Page_Load, the value will be serialized and persisted to ViewState (and in the hidden input). The same for Page_Init, because while view state tracking is enabled during the Init event for each control, the Init events are called in a bottom up fashion (from child to parent), and by the time Page_Init fires, all of the child control Init events have fired and viewstate tracking is enabled. Only if you set the property in the Page_PreInit event (before viewstate tracking is enabled) will it NOT end up in the serialized ViewState (and posted back).

If you want the control events to work, it's important that your property (Text, SelectedIndex, etc) be backed by ViewState, but I guess I can't really see why properties like ForeColor need that sort of state backing? It serves only to bloat the hidden ViewState field and require extra parsing and validation (MAC) when the page is posted back. If controls would have stuck to the guidelines of ControlState in the initial release of ASP.NET 1.0 and not thought caching everything between roundtrips was such a great idea, I guess we wouldn't have this problem.

My point with the rambling above -- ViewState (at least how it was implemented in V1.0) was an abomination and often misunderstood. Like Rick suggested, ViewState is the first thing disabled in the web.config when I start a new project.

foobar
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

> For large data sets (DataGrid, GridView, Repeater, etc) I would argue that it makes sense to cache this data in the Session or Application Cache instead and DataBind on each page load. This is how we did it in ASP.Classic, PHP, perl CGI, etc. Here I would argue that ViewState does more harm than good.

Ug. Putting data into the app cache is useless for me. I have multiple web gardens and multiple web servers. Therefore, I have multiple instances of the application.

The default session state has the same problem. Also, unless you're careful, your users will be relegated to having only one instance of your page open at any given time.

I use a distributed cache to solved these issues. I still use ViewState because I put Viewstate into the distributed cache. So it's really a non-issue for me. RAM is cheap.

foobar
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Oh, as for Rick's criticisms, they're laughable. If you're confused by something like "event complexity", you're not as smart as you think you are. As far as Things That Make My Job Hard, it's down there with things like double-clicking the VS2005 icon.

Front-Controller MVC is... okay. I've been using MVC mechanisms since, well, Java came out (MVC is de jour in Swing), and I've used web based MVC frameworks for a decade now (e.g. ColdFusion has had Fusebox for ages now, which is a decent enough MVC framework). It solves some niggling problems and creates its own.

The thing I find with this whole thing is that it's more the result of some high-profile posers (*cough* CodeBetter *cough*) that have some leverage with the folks at MS that's driving this. Once they get bored/critical with this, they'll just move on to something else that's the Hot Topic They'll Latch Onto.

But then again, maybe my business problems aren't solvable with the pee-pee CRUD apps that everybody else seems to be building.

Eric
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

foobar --

re: ViewState

Can you give me an example what sort of data you're storing/caching in ViewState?

re: Event Complexity

It's not an issue of "being smart". It's an issue of leaky or broken abstractions that end up making the concept they are trying to simplify more complex than it actually is (or originally was). You may be in the top 1% of ASP.NET programmers, but not everyone is. The basics of web CGI programming (as taught in any of the introductory ASP classic, perl, PHP, etc books) are profoundly simpler than the complexity of ASP.NET web applications. There are many people who understand this direct paradigm and are able to create fully functional web sites.

re: non pee-pee CRUD apps

Can you give any examples of the web applications you're building? I'd love to learn some new techniques from the masters.

Bryan Watts
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Eric,

I appreciate your response. First, let me say that I do a lot of control development. Everything I said was from the perspective of the control, especially the Init stuff. Any Page is simply a control with the designation of "root" control, which gives it special properties that first require an understanding of basic controls. My pages themselves don't really do much besides set top-level data and kick off a databind :-)

Solving the issue of stateless requests is the fundamental mechanism which spawned all things Control. This abstraction lifts developers above web mechanics and into their *actual* problem domain. For any web request to any server-side language, the stateless aspect of things dictates some mapping between a form value and its server-side "home".

The control tree of a postback must match that of the previous request, as we are really just de- and re-hydrating the page. A form value is keyed with the corresponding control's client ID; INamingContainer ensures each control's client ID is unique and matches that of the *same control* in the previous page.

We have now defined 1 control in the entire postback which serves as "home" for a form value with any particular key.

As such, ViewState is not an alternative to the scripting method of handling GET/POST values; it is a far more sophisticated implementation. Automating that tedium is the most obvious thing ASP.NET could have done to help web developers; attempts to subvert it or ignore its value are most likely an exercise in futility.

>> You have to wonder what you're really gaining in the long run.

An explicit approach always seems "easier" if the problem spawning the abstraction isn't understood. Look at what you have to do by hand *without* ViewState.

>> What percentage of ASP.NET developers have truly mastered ViewState?

From the above perspective, your question reads as "What percentage of ASP.NET developers know the basics of web and control development?" An amateur contractor may be able to assemble a structure from prefabricated parts, but he's never going to build one from scratch if he can't use a drill.

>> What situations do you advocate the benefits of ViewState?

Any situation in which you find yourself manipulating controls in the context of a stateless HTTP request.

>> I can't really see why properties like ForeColor need that sort of state backing? It serves only to bloat the hidden ViewState field and require extra parsing and validation (MAC) when the page is posted back.

ViewState isn't just for functional data; it is for *anything* that has changed since the page was initialized in the first non-postback request. It is the state of the current view, which is everything your page is.

A value is only persisted when it has changed from the static state of the page (dirty). Setting ForeColor="Red" in markup doesn't result in anything written to the hidden field because that value is *known* to every request.

>> ViewState (at least how it was implemented in V1.0) was an abomination and often misunderstood.

I believe you are misunderstanding it to be an abomination ;-) (I am referring to the concept of ViewState and not its misuse by controls such as DataGrid.)

>> For large data sets (DataGrid, GridView, Repeater, etc) I would argue that it makes sense to cache this data in the Session or Application Cache instead and DataBind on each page load.

This line of thought is the trap which causes ViewState to be painful.

First, let me point out that cached data is subject to becoming stale, which implies SQL cache dependencies or some equivalent. This route has already cost you more pain and processor time than any developer who just loads data when necessary.

Second, if you misunderstand the role of ViewState and the problem it solves, you may be tricked into thinking the only way to create the same control tree on every request is to databind on every request. That is *false*.

Let's take the Repeater for example. When you databind it, it remembers the number of items it created (in ViewState no less!) On any postback, it can just read that value and create that many instances of its template. Each instance is in the same place in the control tree, so its state is automatically restored. Presto!

So ViewState not only houses form values, it also houses values which can give hints on how to recreate a particular structure. This means a postback can recreate the control tree without hitting the database!

Databinding on every request is an obvious hindrance to proper ViewState maintenance (and the main reason why it's painful). Luckily, you don't have to do that!

Also, databinding is an operation which transforms your data structures, which are possibly expensive to load, into their equivalent UI representation. This is potentially orders of magnitude more costly than just rehydrating the control tree via ViewState.

double-oh-seven
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

I take the liberty of paraphrasing the great and late Edsger Dijkstra: "Those who learnt web development using AspNet web forms are permanently brain-damaged."

When AspNet 2.0 came out I thought to myself: "Lovely. Microsoft had spent three years developing it. For sure, the boys of Redmond had re-engineered the controls that emitted and injected junk into every page sent to the client machine." No, they hadn't. Instead, they'd spent the three years developing "css-friendly adapters" so that I might have the luxury of cluttering my aspx pages with junk that was supposed to clean their junk. I wondered. Who are these people? Are they utterly stupid? Insane? Diabolical?

Who's developing the MVC Framework? The same people? Their apprentices and followers?

Scott Guthrie is unleashing it next week. And I shudder with trepidation.

Bryan Watts
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Those incapable of understanding the problems addressed by ASP.NET are doomed from the start.

Eric
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Bryan,

I'm pretty sure I understand ViewState and WebControl development. I've read numerous books and articles on the subject and have been working with them since the early betas of ASP.NET (NGWS). It's entirely possible that my knowledge is not as deep as yours and that you are on an entirely different plain when it comes to ViewState and WebControls, but if that is the case, I'm guessing you're pretty lonely out there all by your lonesome.

I've also been developing web applications for at least 12 years, starting with C++ and perl CGI applications.

I would like a few concrete examples where you absolutely need to enable ViewState and roundtrip 'data' on the client? I'm not talking about scenarios that require ControlState and the data is critical to the advertised functioning of the control (text changed or selected index changed events for example).

Let's take the example of a DropDownList control for a list of states. Let's limit ourselves to the United States and assume there are 50 states. Although we wouldn't have to, let's assume we want to show the full name of the state. Let's assume we have a database table with a list of states in it. When we load the page, we have to retreive the list of states from the database and bind them to the DropDownList. If you do this in the Page_Load event handler (or method override), and ViewState is enabled, the list of state codes and names will be added to the __VIEWSTATE hidden input. When the user submits the form, it will be sent back to the web server, parsed by ASP.NET and the data will be deserialized back into the state list. What if you have 3 instances on a page where you need a state dropdown list. Does it make sense to have to send this extra data to the client, send it back to the server and parse it on each computer? It's extra bytes both ways and extra processing power on each computer involved.

*** NOTE *** -- I know you can get by with ViewState enabled and avoid 'contaminating' the __VIEWSTATE hidden input by *ALWAYS* doing the databind in the Page_PreInit, but where have you ever seen this recommended? It's always been demonstrated as a way to avoid having to call DataBind on postback in your Page_Load event handler.

Don't get confused with what I'm saying. I'm not talking about using ViewState sparingly to keep track of control state (data needed to make sure your control functions). This is prime reason they introduced ControlState in ASP.NET 2.0. I'm pretty sure I explicitly stated this in my earlier post.

I could totally be missing your point... so please elaborate.

Bryan Watts
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Eric,

I didn't mean to imply anything about your background or experience. I work at a consulting company with impressive intellectual capital and this issue trips up everyone. Microsoft's mistake was not in implementing ViewState but in failing to adequately explain it for the average developer. It's always been considered a "control writer" topic, which implicitly relegates it to some upper echelon which may be safely ignored by "page writers".

But, as everyone who is still reading can attest to, ViewState causes more problems than any other ASP.NET paradigm. It's because Web Forms is framed as "page-down" instead of "control-up". Those special properties of the Page "root" control are precisely what confuses anyone moving from top-level page to reusable control development: it's different at the top.

From the perspective of a control, databinding looks like "someone who is responsible for me, because they contain me, will set my data source and tell me when to bind to it. They know what I am supposed to do and when, *not* me. I am but a tool in the master plan of a bigger entity."

From the perspective of a page, databinding looks like: "I am the biggest entity on this page. I will determine relevant data, set data sources on my children, and bind them. They will in turn set data sources on their children and bind them, and so forth. I kick off this entire process but am only responsible for the first logical level of it."

When you databind, you are changing the state of the page. The altered state is recorded in ViewState to ensure that control is in that state on subsequent postbacks. So, databinding only needs to happen if it hasn't happened yet (!Postback) or if the user changes some element of the page, via a postback event.

This realization, along with my previous Repeater example, has led to numerous ViewState "aha!" moments with colleagues who consider themselves well-versed in ASP.NET. Most people don't even realize it relates so intimately to databinding.

On to your questions...

The dropdown example is slightly misleading because the data is relatively static. The list of states isn't likely to change. That makes it a good candidate for application-level caching, which means for any *particular* dropdown, the data can be considered static and we can treat it as such:

public class StateDropDownList : DropDownList
{
  protected override void OnInit(EventArgs e)
  {
    this.DataSource = StateData.CachedInstance;
    this.DataTextField = "Name";
    this.DataValueField = "Abbreviation";

    DataBind();

    this.DataSource = null;

    base.OnInit(e);
  }

  public override void DataBind()
  {
    // Ensure items are not removed if being externally databound
    if(this.DataSource != null)
    {
      base.DataBind();
    }
  }
}


By databinding static data during Init, the dropdown has the correct data and it's not round-tripped. For further optimization, putting one in a user control would enable output caching and remove the need to bind more than once.

ControlState was added as a mechanism to force the existence of what otherwise would be a ViewState variable subject to being disabled. Proper use of ViewState across the board would eliminate the need for ControlState, as they only differ in semantics.

A better example would be a listbox which may be reordered on the client. I implemented this recently and it's a great case study. I will post my development process on that later, after I get something to eat.

Why oh why do I write so much??

Eric
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Bryan,

I like your idea for a derived StateDropDownList, because it's easily reusable. Like you said, TrackViewState on the Control's StateBag (ViewState) has not been called yet in the OnInit method override, so you are free to set any properties of the control without marking them as dirty and forcing them to be serialized into __VIEWSTATE when the containing page is rendered. Would you create a derived control for each time you needed to use databinding?


Back on topic... I really don't think we disagree much on the concept of ViewState.


You're just not going to see 10KB of crap in the hidden __VIEWSTATE input on my pages. :)


ps. Rick, is there a way to increase the timeout on your CAPTCHA? 300 seconds (5 minutes) is rarely enough for slow typers (thinkers too) as myself.

Eric
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

Also regarding this quote:

<blockquote>
I work at a consulting company with impressive intellectual capital and this issue trips up everyone. Microsoft's mistake was not in implementing ViewState but in failing to adequately explain it for the average developer. It's always been considered a "control writer" topic, which implicitly relegates it to some upper echelon which may be safely ignored by "page writers".
</blockquote>

If it takes someone with "impressive intellectual capital" to figure out how to do something relatively simple, you have to start to question the implementation and how it might be too complex or overarchitected, don't you?

Unless of course you're building a technology solely for the 5 smartest developers on the planet.

Bryan Watts
November 30, 2007

# re: What's Ailing ASP.NET Web Forms

>> Would you create a derived control for each time you needed to use databinding?

In this case, the data source is known and static, so we can embed that knowledge in a specialized dropdown. But, this is not a typical databinding scenario.

When you call DataBind() on a control, it internally raises its DataBinding event. Then, it calls DataBind() recursively on each child control, ensuring the entire child tree is databound.

The DataBinding event has 2 purposes: do something with its data source, such as set a Label's text, and set the data sources of child controls.

Notice we aren't calling DataBind() explicitly on child controls. That is because they are databound automatically after the DataBinding event. All we have to do is disseminate data to the next logical level.

Here is a concrete example of binding a set of products to a dropdown list:

public class ProductList : Page
{
  protected override void OnLoad(EventArgs e)
  {
    if(!this.IsPostBack)
    {
      DataBind();
    }

    base.OnLoad(e);
  }

  protected override void OnDataBinding(EventArgs e)
  {
    base.OnDataBinding(e);

    ddlProducts.DataSource = LoadProducts();
  }
}


We override OnDataBinding() like any control event and populate child control data sources. The page, being the "root" control, needs to kick off the databind in the non-postback Load.

Now, let's bind a product to a hierarchy of controls:

public class ProductAttributes : UserControl
{
  public Product Product { get; set; }

  protected override void OnDataBinding(EventArgs e)
  {
    base.OnDataBinding(e);

    if(this.Product != null)
    {
      rptSizes.DataSource = this.Product.Sizes;
      rptColors.DataSource = this.Product.Colors;
    }
    else
    {
      rptSizes.DataSource = null;
      rptColors.DataSource = null;
    }
  }
}

public class ProductInfo : UserControl
{
  public Product Product { get; set; }

  protected override void OnDataBinding(EventArgs e)
  {
    base.OnDataBinding(e);

    if(this.Product != null)
    {
      lblName.Text = this.Product.Name;
      lblPrice.Text = this.Product.Price.ToString("c");;
    }
    else
    {
      lblName.Text = null;
      lblPrice.Text = null;
    }

    ctlAttributes.Product = this.Product;
  }
}

public class ProductDetails : Page
{
  protected override void OnLoad(EventArgs e)
  {
    if(!this.IsPostBack)
    {
      DataBind();
    }

    base.OnLoad(e);
  }

  protected override void OnDataBinding(EventArgs e)
  {
    base.OnDataBinding(e);

    ctlProductInfo.Product = LoadProduct();
  }
}


The DataBind() cascades nicely down the control tree with minimal opt-in effort in each control.

This is what I mean about things being different for pages and controls: the Load/PreRender events, the cornerstone of page development, just aren't that relevant to control development.

Bryan Watts
December 01, 2007

# re: What's Ailing ASP.NET Web Forms

Eric,

>> If it takes someone with "impressive intellectual capital" to figure out how to do something relatively simple, you have to start to question the implementation and how it might be too complex or overarchitected, don't you?

Of course. Being someone with a passion for architecture, I often must throttle my enthusiasm and question the relevance of a new "whiz-bang" technology. That being said, I think, when used correctly, that these mechanisms are among the most revolutionary and powerful since the beginning of web development. Here's why:

The "relatively simple" approach you are advocating is by-hand management of form values and hitting the database to determine a page's structure on every request.

Sure, these _methods_ are simple, but the resultant _solutions_ are not. They require a large initial investment on any new page; to the implementing developer, it is high-friction. It is also a linear scale as to how hard a page is to implement relative to its nesting complexity.

Compare that to the databinding/ViewState approach outlined above. You only need access the database on the first request and set up a simple binding flow, and the *entire page* keeps its state top-to-bottom across all postbacks without any further intervention. Very low-friction. Also, nested structures are handled natively.

And, the most surprising part, is that it's so *easy*! Once all the misunderstandings about who/what/when/where/how/why to databind are wiped away, it's downright simple.

Unfortunately, it's not simple by discovery, due to alternate emphasis by Microsoft. This is the biggest detriment to ASP.NET developers which stray from the most-common use cases. Such bad habits are ingrained by misunderstandings that the easy-to-use, elegant, but technically complex best practice seems almost alien.

Steve Gentile
December 01, 2007

# re: What's Ailing ASP.NET Web Forms

Why does there need to be the constant 'silver bullet' mentality in the Microsoft developers ranks?

MVC is a pattern used by make different languages/technologies. It has a proven track record.

So a Monorail/MS MVC It offers an alternative to the unique Webform web architecture that Microsoft created.

Both sit on top of a greatly designed asp.net architecture allowing for extensibility and customization.

Developers now have an alternative on the way - which is a welcomed thing. Look at other languages and their available alternatives. It offers greater creativity and lends itself to MS developers being able to create solutions using a more traditional approach.

My only real complaint is in your comment on 'maturity'. In my opinion, MVC is 'mature' whereas Webforms are new in terms of approaches to web development. At this point, we who have worked with it, we know it's pain points.

I'd like to add as well that it won't take long to create new great controls in MS MVC.

I've worked with Monorail, and it's proven to be very easy to work with and very powerful to use, so I look forward to an alternative to webforms. You'll see both approaches used for quite some time I imagine.

Thanks for your article.

Michael C. Neel
December 01, 2007

# re: What's Ailing ASP.NET Web Forms

For those that do not understand the basics of HTTP and how servers work with clients, MVC is going to solve nothing. MVC will not magically make the web stateful, or let you know when the client was closed. The dirty underbelly of HTTP will show in MVC just as it does with every other design pattern and framework.

I'm a little lost in your ViewState argument - especially when you recommend ControlState which is stored in the exact same place as ViewState - a hidden field in the page. Using Session means something has to clean up stale sessions - and at the risk of removing data that might still be needed (user in 1/2 though checkout when they get a phone call - 1 hour later they click next and find the cart is now empty). Session in a web farm is worse because it involves a network hop.

Neither approach is perfect, which is why I would say the developer who always disables ViewState is the same as the developer who always uses ViewState.

The only real problem I see with Web Forms is unit testing them - but this is many times the case with web UI. CodeBehind files and a mocking tool can simplify this greatly - which is where the real logic lives. I suppose the purists will want to unit test the rendered HTML, but in practice it's not needed often. Also, good design (such as placing the BLL in an external assembly) can address this same problem.

I'm interested to see what MS will put in an MVC framework for the web as another option developers have. If you're truly looking for speed though, might I recommend generic handlers with response.write?

# ASP.NET MVC Framework

I am fond of MVC . I have done my fair share of Java programming for the Web, and this pattern is nearly

PBZ
December 10, 2007

# re: What's Ailing ASP.NET Web Forms

Bryan,

You may not read this as it's posted many days after your last post, but I just want to say: thank you! I've been reading a lot about this new MVC thing that seems to excite everybody and the more I read about it, the more I think it's a step back rather than forward. Yes, WebForms is not perfect and can easily be abused, but is getting rid of ViewState really the answer. The fact that the whole page is a tree of objects where each control can live without worrying about the rest of the tree is rather powerful.

However, I understand everybody else's concern about the complexity of the framework. You don't truly understand how it all works until you get to write some fairly complex controls. Only then you can truly say "I get it." Unfortunately, like you said, for a beginner all this is a big black box that they can't really see into. A newbie has to swallow a lot of "this is how it's done because this is how it's done" and being unable to see the whole picture abuses the system.

We'll see how this new thing will work better...

gOODiDEA
December 17, 2007

# [导入]Interesting Finds: 2007.12.01

.NET:C#3.0:ExploringLambdaExpressionWhat'sAilingASP.NETWebFormsAlternateViewEngineswi...

cyber sammy
January 04, 2008

# re: What's Ailing ASP.NET Web Forms

HI

You say ASP.NET is losing its coolness. Sorry dude, ASP.NET was never cool.

Ongoing proof of its lack of coolness is MSoft building MVC years too late. Very boring.

I am not disrespecting ASP.NET, it is ok but it is certainly not cool. Groovy and Wicket and Spring - they are cool.

cs.

IS#
January 08, 2008

# re: What's Ailing ASP.NET Web Forms

ASP.Net IS cool and better than a lot of platforms. It's all about architecture and discipline. As for Groovy/wicket, they are tools/languages for solving different problems. I am not saying that they are better or worse, it's just like comparing Ferrari and Aston Martin... pointless discussion!

Andrei Butnaru's Blog
May 18, 2008

# Choosing a framework: should we start to use ASP .Net MVC?

Choosing a framework: should we start to use ASP .Net MVC?

Mike Gale
July 28, 2008

# re: What's Ailing ASP.NET Web Forms

This article still raises a bunch of concerns that resonate.

At root we've got this foundations of sand issue (leaky abstractions). The protocol, the client... are not designed for what we're doing. While those are wrong I can't think of a solution that is going to be simple, powerful and just feels right.

Having said that the job could have been done better. There was experience in how to build better XHTML and to style it, how to drive it with code... but many of the guys in the trenches who built ASP.NET hadn't got to grips with it. This landed us with true ugliness under the skin (especially in the early versions) naming container is a killer, hard to use CSS, using client side code (initially) seemed to be actively sabotaged, viewstate as you say not thought through, where is the developer support for that rich event model (I still don't see it, and it would just make things work if done well), the postback model, compilation models that never quite give you what you want and to cap it all the difficulty of testing.

Giving credit where it's due the framework has got better. This at the expense of more complexity. Some people love the complexity. I'd rather have less so that I can get on with the job instead of wasting brain cycles on figuring how the event model messed me up (or whatever).

Great article. Maybe the real answer is to substantially reform the web we know so that it can sensibly do what needs doing without mindless complexity and tricks.

WINT
September 13, 2008

# re: What's Ailing ASP.NET Web Forms

Let me start by saying Microsoft to their credit have been influenced greatly by the "community". That statement could not have been said a few years ago.

In my opinion Microsoft's approach to the development of ASP.NET Web Forms all them years ago was very much commercially influenced. Microsoft's focus was to provide an architecture for the web that provided "mass appeal" by easing the transition from the development of stateful desktop applications to stateless web applications. This approach enabled thousands of MS developers world wide to "dip their toes" easily into the world of web development without any major barriors. Remember the secret to the success of any software vendor is adoption. Look at Windows for example!

ASP.NET Web Forms is great in many respects. However the solution is also flawed in many areas e.g. to name but a few; Viewstate bulk and Server Controls that are desinged to promote RAD but infact harbour development due to their lack of customisability.

Classic ASP had a tendency to result in hacked together sites comprised of spagehetti code and infinite nested includes! ASP.NET Web forms, although a far more mature platform for development, in many instances, still has a tendency to facilitate hacked together sites. Developers can simply get away with murder! I have encountered numerous ASP.NET Web Forms websites that are developed by people who have a complete disregard for the principles of OO programming.

Microsoft have provided an excellent coding platform that is sadly implemented regularly in a sub-standard way. Unfortunately, ASP.NET web forms, by design, faciltates this. Adoption is key remember!

The MVC design pattern is a far more grown up model (thank god for RUBY!), that is not born out of commerciality but by best-of-bread programming. MVC by design separates concerns. MVC promotes the development of a solution to the problem domain using structured object orinientated models, and whats more, the development lends itself perfectly to being test driven, and therefore as close as can be to being bullet proof prior to the UI concerns being bolted on and displayed in a web browser.

The beauty of MVC (apart from the purism!) is that it promotes efficient simultaneous development. Each specialist within the team is able to do their thing without stepping on the toes of their collegues and is a far more a productive model than ASP.NET web forms.

I have worked with Monorail for the last couple of years and am extremely impressed with the the ASP.NET MVC implementation. It will take time to mature but I am convinced it is the way forward.

Anon
February 16, 2009

# re: What's Ailing ASP.NET Web Forms

ASP.Net MVC has turned out to be a pretty impressive framework. Personally, I've been using a custom viewengine based on the StringTemplate engine.

http://websitelogic.net/articles/MVC/stringtemplate-viewengine-asp-net-mvc/
http://code.google.com/p/string-template-view-engine-mvc/

It's worth a look if you're new to the framework and still hunting for viewengines. It's so refreshing to have the power of the .Net framework, without the noose of WebForms.

Aaron Clausen
May 18, 2009

# re: What's Ailing ASP.NET Web Forms

Excellent to see a prominent MS guy saying exactly "how it is" with ASP.Net.

I am one of those "hard core" web developers who's ALWAYS disliked ASP.Net from the very first time it was released. I used to code in ASP classic (among other things) and I've coded up countless windows forms, but web is my main focus. I've now used ASP.Net web forms for 5-6 years. But I've used many other different web development languages and platforms, so I can compare accurately.

ASP.Net web forms is hands down the most frustrating one to use of all of them. It is designed for traditional windows forms developers who have to drag and drop everything and its a massive fail in capturing the proper way the web works. Exactly as Rick has summed up. It creates bloated, inefficient, non-standard, frustrating, second rate web sites.

I gave it a massive chance (years of using it and coding tens of sites in it). But only for work purposes, I never use it by choice. Lots of large companies use it simply because everything else in their environment is MS so it makes sense on the surface to just go with it, because it talks to their SQL Server databases and active directory and so forth.

The other web platforms are miles ahead and developers (like me) can achieve so much more in so much less time. I constantly am frustrated by the annoying, niggling things that get in your way using web forms, it really is ridiculous. Literally some things that would take 30 seconds in any one of (PHP, Colf Fusion, JSP and even Classic ASP) can take up to half an hour in ASP.Net web forms. Putting it straight, PHP 5 years ago was still way ahead of where ASP.Net is right now. Sure ASP.Net is so scalable and is a server-side programmers dream, everything can be nicely OO inherited and blah blah, but the bottom line is that it still produces garbage HTML and is very inflexible with what it eventually spits out on the client side, once you've finished coding all all the fancy control-driven, super inheritance OO magical wonderland. Bottom line, bad HTML, this is what your web site is made of, the users don't see how lovely and theoretically perfect and scalable all your controls are at design time, they don't care, they only want clean, efficient HTML that's renders the site perfectly and cleanly. Any web dev platform ultimately just manipulates and spits out HTML, THAT'S IT.

The web developers who are at the "intermediate" level and haven't seen all that much and who weren't around in the early days knowing HTML/CSS/JS exactly perfectly by hand don't understand because they can't appreciate the bloat. They are ignorant in not knowing HTML, web standards or accessibility and they are happy drag and drop'ing ASP.Net web forms and being ignorant as to the bloat that's being created. These are NOT web developers. Your sites generated from ASP.Net web forms will always be second rate, but you'll be happy being ignorant of this fact and thinking all is well.

Ignorance is bliss (Look that up if you're too stubborn to admit you don't know what this saying means).

Cheers and awesome work on taking the time to spell my thoughts out exactly Rick and full kudos for putting it out there as you're an MS guy.

Aaron Clausen
May 19, 2009

# re: What's Ailing ASP.NET Web Forms

Well well well, I cracked with web forms and have been trying ASP.Net MVC.

First impressions = WOW! They have actually listened/learnt from the web forms disaster.

Immediate improvements that I noted in about the first 10 minutes of using:
- No form tag forced into your rendered output - finally!
- No stupid "postback" concept.
- No ViewState - Yeah boy!!!
- No auto-generated lump of inline JS code for __doPostBack slammed into each and every page against your will. Wasn't this a super obvious one!?
- Clean, natural, absolute URLs such as having img src="/images/image1.gif" just work! You don't need to add runat=server and ~/ to get it to find the root. This was another EPIC FAIL of web forms. Why should a simple HTML image need to bog down the server by needing to be processed server side. With MVC I can just reference my URLs naturally like that, and it doesn't interfere with my clean HTML and it just WORKS.

Thank you MS so far for listening.

I've already made a dynamic selectable navigation tabs control which works a treat based on SiteMaps and I've brought across half of my web forms project which was in limbo into MVC, its not finished yet. But for me, development time is dramatically speeding up because I can work directly with the web and not be burdened by leaky web forms abstractions that also chew up brain cycles for no benefit.

So far top marks for MVC.

Note: I've NEVER been an MS=hater. I just like good/smart software, I don't care who writes it. If MS make something great, I'm the first to fully get behind it. I'm not one of these open source "I hate everything MS" dweebs. But the truth was that web forms blew.

I feel like I can now be at a corporate job, but inject my creativity and client-side scripting skills into my work to achieve whatever results I desire. Where as before with web forms, I was so burdened and held back. This will only benefit the company and the resulting output of my work.

Aaron Clausen
May 20, 2009

# re: What's Ailing ASP.NET Web Forms

OMG ASP.Net MVC is proving to be exceptionally good. Its better than I even expected Microsoft to get it. I am thoroughly enjoying it and now even considering using this for my own "outside of work" projects. I'm using LINQ to SQL, jQuery and AJAX all within MVC, so there are a few learning curves, but fairly efficient ones and everything just makes sense and "works" how my brain expects it should naturally.

For any hardcore PHP/RoR guys, this is definitely a nice option for you to consider one day if you ever need to change. C#'s syntax is miles ahead of PHP and way more advanced and capable. SQL Server is the world's best DBMS in my opinion too, so these are some side benefits. I know mySQL is an AWESOME product for free, but it will never beat SQL Server in outright features and capabilities.

The cost of hosting and SQL Server licenses might be another thing though :(

Aaron Clausen
May 31, 2009

# re: What's Ailing ASP.NET Web Forms

Uh oh, something scary is happening..

I had to use PHP again all day Sunday to do some work on my blog.

I noticed just how dated PHP's syntax feels now - quite clumsy and verbose in a lot of ways.
Still very clean and direct to "super quickly" make changes to any web site, but the syntax just feels really stupid/dated now.

I have really become used to C#s' easy flowing, logical and well-structured syntax. C# feels about 5-10 years more modern compared to PHP's very dated syntax.

And now that Microsoft have realised web forms was a flop and built MVC, I'm a happy man. I am truly finding MVC to be exactly what I'd hoped that web forms always was. It's nice and logical to use and non-obtrusive, it doesn't get in my way. Plus I get all the benefits of C#'s bountiful world of libraries and classes to go to town with, plus the strength of proven (but $$$) SQL Server for the database platform.

I think this might be a turning point where I go back to using MS for web development. And I NEVER thought I would ever say that. (In the old days, all of my sites were done in classic ASP, I only moved to PHP after web forms came out and I found it so annoying).

Claudio Friederich
May 27, 2010

# re: What's Ailing ASP.NET Web Forms

Personally, I feel that ViewState is one of the greatest features of ASP.NET, and I recommend that developers use ViewState for all page state data and even instead of SessionState. In fact, I recommend avoiding using SessionState at all if possible, and using ViewState for everything. Why? For one and only one reason. SessionState times out, ViewState does not. I am speaking now as a user, not as a developer. I have had it with visiting a web site, typing in a bunch of form fill-in information, having to leave for a few minutes, and coming back to continue, and having the page pop up a message saying "I am sorry, but the page has timed out. Please log in again (and start all over, waste your time, and you have lost the form fill-in you already did, so sorry)." These sites do this because they store state data in Session state, which times out. If they used ViewState, the user could come back hours later, the server on the other end could even have been rebooted, but the user can continue as if nothing had happened, which is how it should be. Remember developers, your job is to make life easier for USERS, not to say to users, "look how beautiful my client-side script is, just click View Source and be amazed." Ok, so ViewState bloats the page by 50k. Who cares? Typical web pages have images much larger than this all over the place, and most of the images are nonessential. So client-side script in ASP.NET is ugly. So what? most client-side script that is not automatically inserted is nonessential. Using script for essential tasks is a mistake anyway, since there is no way to guarantee it will execute right on any given client. Half the pages you visit say "Done, but with errors on page." A language whose processing is as flaky as client-side script cannot be relied on for essential purposes. My first ever web site (built in ASP.NET 1.0) was not pretty, had no graphics, and not a word of my own script, and used ViewState with abandon. But it was stone-hard stable, never errored out, and performed multi-layer hierarchical database viewing and updating. That is more than I can say for half the sites I visited that use all the fancy developer-done stuff, built by web experts, not come-from-Winforms developers like me, that "bloated" ASP.NET does for you.

Keith B.
July 28, 2010

# re: What's Ailing ASP.NET Web Forms

A great post, a classic even -- thank you! Although I'm a little late to the party here, I feel compelled to post. I agree pretty much completely with the points made: ASP.NET is powerful, scalable, and mature; yet flawed in fundamental ways. If you understand it well, there's little you can't do with it -- with the exception of "client ID voodoo" (addressed in ASP.NET 4.0?) and a few other things. But if you don't -- particularly key elements like the page lifecycle -- you're in for a world of pain.

As many have pointed out, one of ASP.NET's great failings is that its architecture does not provide much guidance. The simple evidence is that it's easy to write ASP.NET web pages that don't work. MVC on the other hand, at least has the overarching model-view-controller paradigm, which does provide guidance. (I'm not going to comment on the whole MVC vs. ASP.NET thing -- seems like there are appropriate situations to use each of them.)

I particularly agree that ASP.NET does a poor job with "separation of concerns." For example, there's no enforcement of a data model -- including when and where it should be updated. There's no abstraction of the "first page load" concept -- only the functional IsPostback hack. Lack of testability is another big one. And yes, Microsoft ASP.NET has lost its "cool factor."

And there's little explaining how to architect an ASP.NET web form! I was doing an architectural review of a few ASP.NET applications for a client, who clearly didn't understand how the page lifecycle worked with the page model. To my amazement, I couldn't find any guidance on "best practices" in Web Forms design. There appear to be no resources out there which explain the page lifecycle clearly -- e.g. a mental model that developers can use to truly understand it.

I blogged about this recently in a post I called "ASP.NET's Dirty Little Secret" at http://j.mp/bUTOyo. I scanned articles, books, blogs and comments for several days to find coherent guidance on the lifecycle, without much luck. I imagined the damage to the Microsoft ASP.NET "ecosystem" as a result: probably MILLIONS of developer-hours wasted debugging apps, and lots of frustration with ASP.NET technology.

I would glad to be wrong on this count, but I don't think I am.

-- Keith

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024