Thursday, April 3, 2008

View State: do not forget to manage!

View State is an essential part of ASP.NET and not paying proper attention to how it's set up in your web application can give you some surprises sometimes not very pleasant ones. For those who wants to refresh their memory about ASP.NET View State I recommend to start from this good article by Dino Esposito. The article is not very new but it's still relevant and it covers many topics that are actual for today's ASP.NET programming.

So now as the background is covered I would like to focus on two main aspects that have to be considered in regards to the View State: performance and security.

What is it to consider performance-wise in regards to the View State? In a nutshell as larger the View State as larger a browser payload as more time is required to process the page on both server and client side meaning worse user experience.

What does the View State have to do with security? As the View State is publicly exposed to a web browser and contains internal data of the ASP.NET page and user controls there is always a risk that its content can be altered and data compromised that could lead to some unexpected behavior of a web application.

So is it inefficient and dangerous to use the View State in your application? Answer is NO: the View State is extremely useful and sometimes absolutely essential for the ASP.NET web application to work properly but don't assume that the default View State settings and behavior are always the best choice for you: always manage them consciously.

Is there best practice about the View State? Of course and there are some of them.

  1. Always explicitly turn off the View State for any control that does not require it to operate. Examples are: Label control, Literal control, Image control, HyperLink control, etc.
  2. If your page does not perform a post back and there is no complex data binding there is a good chance that you can turn off the View State for the entire page in the @Page directive. If you doubt simply try and see how the page works with the View Stated turned off.
  3. If you use complex template based server controls like Login control or CreateUserWizard control, for instance, convert them to templates and check out that the View State of all the child controls is properly managed (always look for Labels and Literals).
  4. When optimizing your ASP.NET application use some third-party browser-based tools to analyze page's View State content and reduce its size as much as possible.
  5. If you use a client-side View State always encrypt it.
  6. Consider moving the View State to a server side: besides security benefit of not exposing the View State publicly and reduced http payload the View State is processed faster on the server. Be aware about server memory consumption when using the View State on the server side. It's much easier to implement the server-side View State in ASP.NET 2.0 then it was with ASP.NET 1.1. Look at the example here.

That's mostly it. Follow the best practices above and feel confident about having your web application's View State managed properly.

Ensure Default Values in ASP.NET Server Controls

Many of ASP.NET server controls base their internal HTML rendering algorithms on the values of their properties. Developers are mostly aware of those properties (not always about their roles in the internal rendering process though) but don't always realize the importance of the default values.

From my experience there is a common assumption that if a property appears empty in the Visual Studio property window that means the default value is empty. Not always true and can be harmful for the output HTML content! Luckily there is always a way to ensure the default values of the properties in ASP.NET markup (.aspx, .ascx). Here are a few examples.

SiteMapPath server control

It has a string property SkipLinkText that by default appears empty in the property window. But in reality if it's not set it's populated from the embedded resource string. That effectively leads to a difference in HTML rendering that does render an <img> tag inside the breadcrumb path with the height and width attributes set to 0 (don't ask me why!).

Some browsers react inadequately on such the HTML if some CSS styling applied to the breadcrumb content. For instance IE6 does not honor a line-height attribute if there is an in line image inside the paragraph.

So to ensure that unnecessary HTML is not rendered in this case always use SkipLinkText="".

ValidationSummary server control

It has a string property ForeColor that defines the color of the text appearing in the control and is prepopulated with the Redvalue. Having a value in this property effectively leads to the control rendering out an inline styling "color:Red;". But if you want to define a text color in the CSS class that you apply to the control you have to explicitly set this property to empty value ForeColor="" otherwise it will always render out the inline styling which will effectively override your CSS settings.

CreateUserWizard server control

This is quite a complex and sophisticated template-based control that comes with ASP.NET Membership framework. From the first sight you assume some degree of intelligence built into the control based on its complexity. For instance, that it does validate user input and render error messages if something is wrong. And it's true except that it does not validate e-mail address string against a regular expression unless a property EmailRegularExpression is set to a proper value and it is not by default. Also it does not provide a developer with such an expression even though it is built into a standard RegularExpressionValidator control.

So be careful and don't forget to set this property EmailRegularExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" otherwise you will be surprised that a user can enter some garbage into the e-mail field and is not stopped doing that.

So above there are just some examples illustrating an importance of paying attention to such details as default values of the server controls' properties. I am sure you can find more examples based on your own experience.

Using .skin File

Also there is another more efficient way to ensure that the critical default values are properly set across a web application: just add all the default values that you want to ensure to your default .skin file. For example, for above mentioned controls add the following lines there:

<asp:SiteMapPath runat="server" SkipLinkText="" />
<asp:ValidationSummary runat="server" ForeColor="" />
<asp:CreateUserWizard runat="server" EmailRegularExpression="\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*" />