Resources

Client side state management in ASP.NET

For applications scaling to thousands of users should strongly consider using client to store application state. Removing this burden from server frees up resources. Techniques valuable for storing state information at client:

Choosing client or server side state management

If state management info is stored at client, then it is submitted to server with each request.

Can store majority of data at server and use client side mechanisms purely for user tracking - i.e. tie user up with information stored server side.

Client side advantages:

Server side advantages:

There is also persisted state - data stored in database. Could decide to store all info in database, but this may put too much pressure on database. In this case may be better to store real, transactional data in database and rely on other techniques for managing the transient state data.

View State

Mechanism used by ASP.NET to store user specific request and response data between page requests. Not stored by server, instead saved in page's view state and sent in page's response back to user. This view state is then returned with their next request. When page processed ASP.NET uses the view state to reset property values of page and its controls.

Unless disabled, this is a part of every ASP.NET page.

The Page.ViewState property (of type StateBag) provides dictionary for retaining values between multiple requests for same page. When page is processed, current state of page and controls is hashed, compressed and encoded into string and saved in page as hidden HTML field called __ViewState. If data too long for single field (see Page.MaxPageStateFieldLength property) then ASP.NET performs view state chunking to split it across multiple hidden fields.

View State Security

View state can be tampered with as it is just a hidden html field.

View state contains message authentication code (MAC) that is used by ASP.NET to determine if it has been tampered with. Helps ensure integrity without having to encrypt view state contents - can rely on MAC and base64 encoding for obfuscation.

If do have very sensitive information to place in view state, can encrypt it using ViewStateEncryptionMode property of Page object.

<@ Page Language="C#" ViewStateEncryptionMode="Always" %>

Will secure view state, but decrease performance of page processing. Also increases size of data being sent between server and browser.

Can enable view state encryption for entire site by setting viewStateEncryptionMode attribute on pages element in web.config file:

<configuration>
<system.web>
<pages viewStateEncryptionMode="Always" />
</system.web>
</configuration>

It is more secure to store sensitive data on server and not send it to client.

Disabling View State

View state enabled by default for all pages and controls - includes label and literal controls that may never be needed to include as part of view state. Should always minimise size of view state. Disable view state for controls, or entire pages, where possible.

At page level use Page.EnableViewState and Page.ViewStateMode.

At control level use Control.EnableViewState and ControlViewStateMode

ViewStateMode only has effect if EnableViewState is true. By default ViewStateMode is Inherit which causes control to inherit pages view state.

If don't change ViewStateMode then setting EnableViewState to false for a page then all its controls view state are also disabled.

To disable control view state should set its ViewStateMode to disabled

Description Page.EnableViewState  Page.ViewStateMode  Column.EnableViewState  Control.ViewStateMode
Disable view state for page, but enable for specific control  True Disabled True Enabled
Disable view state for page, disable for specific control True Disabled False Disabled or Inherit
Enable view state for page, but disable for specific control True Enabled False Disabled
Enable view state for page and for a control True Enabled True Enabled or Inherit

 

Can disable view state in web.config by setting enableViewState to false in pages element:

<configuration>
<system.web>
<pages enableViewState="false" />
</system.web>
</configuration>

For form with 20 controls, view state easily exceed 10KB.

Can compress viw state by enabling GZip compression on the web server.

Can compress view state without compressing rest of page by overriding Page.SavePageStateToPersistenceMedium and Page.LoadPageStateFromPersistenceMedium which serialize view state data. Within overriden methods use System.IO.Compression.GZipStream to compress / decompress view state data.

Custom View State Data

Can use view state to persist custom data between page requests - don't need to be associated with control.

Use ViewState object like a dictionary:

ViewState["lastvisit"] = DateTime.Now;

Note content of view state is for page only. View state does not transfer from one page to another (as a cookie does). Thus only use to store values between requests to same page.

Moving View State

Rendered at top of page.

Can place elsewhere by overriding Page.Render method and then use string manipulation to move hidden state field to elsewhere in page.

View State and Control State

Disabling view state for a control is problematic for control developers. A custom control may need view state like behaviour that cannot be disabled by a developer.

Control state allows storage of property value information for a specific control.

Cannot be turned off by developer, but should not be used in preference to view state - only where really necessary.

To use override OnInit method for control and call Page.RegisterRequiresControlState. Then implement SaveControlState and LoadControlState for the control - in these methods save and retrieve control state information.

Hidden Fields

ASP.NET uses HTML hidden fields to store data. Hidden fields are simply input fields embedded in page. Not displayed to user. Sent back during page post.

ASP.NET provides control for you to create own custom hidden fields. Store data in its Value property.

Only store information for single page. Not useful for storing session data used between page requests.

Have no built in compression, encryption, hashing or chunking - very vulnerable to user tampering.

Must submit pages to server using HTTP POST - cannot use HTTP GET (as when user clicks link on page).

Cookies

Small amount of data stored at client and passed with requests to server.

Persistent cookies written to text file on client - survive event if browser closed and re-opened at later date.

Temporary cookies held in browsers memory - lost when browser closes.

Most common use is to identify user as they visit multiple pages within site. Can use them to store other information, e.g. user preferences.

By default ASP.NET uses cookies to track sessions. If session state enabled then cookie used to identify session.

Most flexible and reliable way of storing data at client, but users can delete them at any time.

Don't solve problem of users moving from computer to computer.

Reading and writing cookies

Web application creates cookie by sending it to client as HTTP header.

To add cookie to cookies collection call Response.Cookies.Add(new HttpCookies("userId", userId);

To retrieve cookie value sent back by browser use Request.Cookies("userId").Value;

To delete cookie, overwrite the cookie and set an expiration date in the past.

Controlling cookie scope

Cookies should be specific to website domain or directory within that domain. By default browsers will not send cookie to website with different host name.

Cookie scope determines which pages have access to information held in cookie. If limited to directory only pages in that directory have access to cookie, e.g.:

Response.Cookies["lastVisit"].Value = DateTime.Now.ToString();

Response.Cookies["lastVisit"].Expires = DateTime.Now.AddDays(1)

Response.Cookies["lastVisit"].Path = "/MyApplication";

To expand scope to entire domain...

Response.Cookies["lastVisit"].Path = "contoso.com";

Setting path to domain allows cookie to be used by any server within domain. Can restrict further by providing full host name, e.g. www.contoso.com

Multiple values in cookie

Cookie size dependent on browser, each can be up to 4k in length.

Limit of 20 cookies per site.

Can store multiple values in single cookie, e.g.

Response.Cookies["info"]["visit"] = DateTime.Now.ToString();

Response.Cookies["info"]["firstName"] = "Tony";

Response.Cookies["info"]["border"] = "blue";

Cookie properties such as Expires, Command and Path apply to all values in single cookie. Cannot control these at individual key level.

Access individual values of cookie using Request.Cookies in same way.

Query Strings

Appended to URL.

Store values for specific page.

Separated from URL by ? followed by parameter name, = and then value.

Values sent to page via query string can be retrieved via Page.Request.QueryString property, e.g.:

Request.QueryString["setlang"];

Provide simple, but limited way to maintain state information.

Easy way to pass info from one page to another.

Some browsers impose limit of 2083 characters on length or URL.

Must submit page using HTTP GET command to make values available at server.

Parameters and their values are visible to user in their address bar.

You should expect users to change data in query strings - always validate data provided to server.

Their data is included in bookmarks an dURLs sent via email - in fact only way to include state data when copying and pasting URLs to another user - for this reason use query strings for any info that uniquely identifies page even if using another state management technique as well.

To allow URL to be sent by email limit length to 70 characters (including http://).

To allow URL to be sent via IM limit length to 400 characters.

Common mistake is to allow users to navigate search results, but not to validate query string provided. Users can then set number of results per page to a very large value, e.g. 10000. Makes very easy for attacker to perform DOS attack!

Adding query string parameters to URL

Modify URL for any hyperlink user may click.

No tools built in to ASP.NET to simplify creation of query strings.

Reading query string parameters

Access the Request.QueryStrings collection, e.g.

Server.HtmlEncode(Request.QueryString["page"]);

Should always encode cookie or query string values via Server.HtmlEncode before displaying value in html webpage. This method replaces HTML code with special characters the browser cannot process.

To provide extra protection .NET will throw exception if it detects HTML or client-side scripting in a query string - but this feature can be disabled by system administrators so do not rely on it.

Downloads