ASP.NET 4.0 & Why it Matters

I hear a lot of overused and overloaded terms these days like “leaky abstraction” when talking about WebForms.  As people repeat these items like robot drones, I wonder if they truly understand what it means, and more importantly how it affects a developers ability to build software.  But whether it’s a group of robot drones, or an increasing number of well educated software engineers, we’ll leave for the subject of another debate.  Back to the matter at hand.  Of all of the WebForms complaints, it usually boils down to a few key issues – ViewState, ID generation and HTML Markup & Postbacks; each of which is undergoing changes in ASP.NET 4.0.

ViewState

To understand the first issue of ViewState, you have to understand the ViewState model.  It works recursively in nature, with each control responsible for initiating the loading and saving of ViewState from it’s child controls.  The problem comes when you turn off ViewState at a root level.  Since the parent control is no longer storing ViewState, it’s child controls get ignored.  Basically, you can turn ViewState off selectively for children, but you can’t turn it on selectively if it’s disabled for the parent control.   The solution?  ASP.NET 4.0 introduces the ViewStateMode pattern which is separate from the EnableViewState property.  ViewStateMode has 3 values, Enabled, Disabled and Inherit (the default).  When ViewStateMode is set to disabled, any child control that is set to Disabled or Inherit will have it’s ViewState turned off.  If a parent control has ViewStateMode=Disabled, and the child control has ViewStateMode=Enabled (the important new scenario), the child control will still have it’s ViewState saved.  This in essence, is what the feature is all about.  The net gain for a Web developer is a lighter weight page, because you now have the ability to turn off ViewState in places that you didn’t really need it on in the first place.  

ID generation

Have you ever taken a look at the html markup produced by an ASP.NET WebForms application?  I have.  Actually, I spend a good portion of my time examining html markup and discerning how a page can be made lighter or faster based on what I see.  One of the big offenders happens to be ID strings.  If you want to address an element, you need to give it an ID.  If you want to address it uniquely, you need to come up with a mechanism to make that ID unique.  In ASP.NET WebForms this was done by pre-pending the parent control’s id to the ID string of a control.  The problem is that as applications became more complex, so did the control hierarchies, which then caused UniqueID and ClientID strings to become unmanageable.  Looking at an application today, it’s not out of the question to see something like “contentPlaceHolder1:ctl0:ctl0:UpdatePanel1:Panel1:GridView1” Now if you use that string a few times to address id’s or create css class names, you’re bloating your HTML.  Even worse, you’re creating a recipe for cascading failures if you ever change the containership or the ID of one of the parent controls.  Suddenly, your element’s ClientID has changed, and you need to go through and update your code. 

In ASP.NET 4.0, you’ll have the ability to set the ClientIdMode to “Static” which solves most of these problems.  With a Static ClientIdMode, the ID string you set for the control, is the same string that will be used for the ClientID.  This has the benefit of being less fragile, and gives you the ability to clean up your markup by shortening ID’s considerably.  The drawback to using ClientIdMode=Static is that ID’s will not be ensured to be Unique by the framework, making this a manual task for the developer.  Not sure about you, but if that’s the biggest challenge of my day, I’ll be smiling.

HTML Markup & Postbacks

Postbacks were the bread and butter of ASP.NET 1.0.  Luckily ASP.NET has come a long way since then, and developers today understand that creating a good User Experience means limiting postbacks.  The amount of HTML rendered to the client also has a direct correlation on User Experience.  The more HTML/Markup, the longer a page will take to load.  ASP.NET 4.0 improves this key scenario by adding Client-Side DataBinding and templating.  Think of client-side templates as a repeater that get’s populated by JavaScript.  Why populate the repeater on the client-side rather than the server-side?  It’s a matter of multiplication.  Take the same 4 lines of HTML in a repeater template and multiply it by the number of items in your datasource.  Now push all of that HTML down over the wire to the client.  Make matters even more interesting, use the same datasource to populate a grid.  In a typical scenario, you’re pushing the same data down two times, once for the repeater, once for the grid.  If you had that data available as a client-side DataSource, you only send the data down once, and re-use it on multiple controls.  At the price of a little extra processing power to create the dom elements through JavaScript, you get the benefit of possibly drastically reduced HTML markup, and free yourself from relying on Postbacks in order to populate a list. 

The three features listed above are just a short list taken from the ASP.NET 4.0 features whitepaper.  Even in this short list, it’s easy to see that ASP.NET 4.0 is changing the face of WebForms.  Many of the concerns that developers have expressed and many of the advantages that MVC touts over WebForms are being addressed.  The point is, WebForms isn’t dead, it’s quite the opposite. 

10 Comments

  • Very interesting info. Thank you.

  • Die WebForms! Die!

  • Regarding ClientID: If you hardcode your JS to your HTML code that's a form of coupling and I'm surprised people don't call up on that. Why not just pass those IDs to the JS code and work from there. You'd end up with a much cleaner and maintainable JS code.

    "The drawback to using ClientIdMode=Static is that ID’s will not be ensured to be Unique by the framework, making this a manual task for the developer. Not sure about you, but if that’s the biggest challenge of my day, I’ll be smiling"

    You're advocating bad design practices. Setting the client id mode to static is a hack, and nothing more. It would be like the framework allowing you to do your own memory management because you know better... It should be used only when you can't change the code that depends on those IDs, and if you can't do that then you have another problem on your hand.

    This whole ClientID thing is actually one of the good things of the leaky abstraction you're talking about. If we didn't have mycontrol.ClientID then yes, all this would be warranted. What's really leaky and based on your post won't be fixed in 4.0 is the fact that I can only have one form on a page. HTML allows and browsers are optimized for multiple forms on a page, but ASP.NET WebForms doesn't, hence the leakiness.

  • Responding to Peter's comment: Tony did mention referencing ClientID in CSS (not just javascript), and this is harder to acheive.

    I tend to add class names to my elements rather than using the ID, like class="myClass" or CssClass="myclass" and then use that from the CSS instead of reference via ID.

    Although I do agree with Peter that from javascript I have never had a problem accessing via ID, In my javascript, I just emit the generated ClientID, and assign a javascript variable to it. For example in an ASP.NET page in a script block I do this:
    var messageID = $("#");

    The great thing is Visual Studio will actually give you a compile time error if that block is invalid. In other words, if you renamed the ASP.NET Message control and did not update the above line you would get a compile time error! Very cool.

    So I for one welcome the ability to statically assign ClientIDs, but it has not been too much of a pain for me with the current version of ASP.NET.

    David

  • @Peter - Good points, and actually I agree that ID's shouldn't be hardcoded when possible.

    The current ClientID solves a specific problem - uniqueness. However, it creates another problem - long strings. The ClientIDMode=Static gives developers an option. They can forego the auto generated ID for something shorter. This isn't a hack at all, this is an alternative.

    I agree that hardcoding JS to your HTML creates a tight coupling bound to break, but it's sometimes unavoidable. In my own code I use a server-side emit to assign my variables like "var id= ''. This works great most of the time, but there are cases when this isn't possible and hardcoding is requird.

    After working with WPF and Silverlight, I think that Static Id's are much more useful than the ASP.NET auto generated UniqueID's. Even the fact that in XAML, you don't have to specify an ID, makes more sense than the ASP.NET model of always requiring an ID. An ID is used to address a control. If you don't need to address that control, you shouldn't need to specify an ID.

    All in all, I think the added ClientIdMode is a great thing. In most cases my ID's are Unique anyway. It's unlikely that I'll have two textboxes named "txtName" in my application. But it is extremely likely that "txtName" will be n levels deep in a control hierarchy, and end up with a UniqueID that is big and bloated, and totally unnecessary.

  • @David: I do the same thing, I almost never use ID based CSS styling. As far as JS code, I tend to write stuff like SomeFunction(someId) that could be placed on a separate JS file and when I call that function from ASPX/ASCX I use, for example: onclick=

    What makes that code harder to write than it should be is the alternating single quote / double quote restriction. That is one aspect of ASP.NET that doesn't make any sense to me.... What makes even less sense is why it hasn't been fixed yet :(

    @Tony: It's nice to have this options, and it depends from case to case. I'm definitely not arguing against having this in the framework. I guess my point was that it shouldn't be used as a way to circumvent framework.

    We have a system here where the website is more or less entirely build dynamically from a database with each bit being some kind of user control placed on the page by the client. In this case the way the auto generated IDs work is perfect. From inside a user control I don't have to worry about how many times the UC will be on the page or what page it's going to be on.

  • I am a little bit confused with new VewState behavior. Can I disable it on a page level and enable for page inner controls? Or I still have to keep ViewState on in page directive?

  • @Loginov - You can disable it at the parent control level (the page), and enable it at a lower child level.

  • stumbled upon this post quite by chance. i'm a front-end coder. i recently built the static template for a micro-site that would be used by schools and the public sector, and therefore had fairly stringent accessibility requirements (spec requested AA, i delivered AAA). having handed the static mark-up to the .net developer, for him to cut up and use as he saw fit, imagine my dismay when i noticed that part of the page was not rendering properly. inspecting the mark-up i noticed that the ENTIRE page was wrapped in a form. "what the devil is all this about?" i enquired. "oh, that's needed for the postbacks" was the reply.

    this completely renders any page highly inaccessible, as screenreaders behave very differently when rendering forms. very differently indeed. worth considering next time you build a site using .net...

  • Client-Side DataBinding and templating looks like just what I need. Thanks for the info.

Comments have been disabled for this content.