"Invalid Viewstate" With Load Balancers

If you are using a round-robin (non-sticky) load-balancer (and perhaps even if you aren't) you may run into a problem where the client gets errors during the checkout process.  Checking your event log you might find the following error (non-essential information removed):

Event Type:        Information
Event Source:    ASP.NET 2.0.50727.0
Event Category:                Web Event
Event ID:              1316
Event code: 4009
Event message: Viewstate verification failed. Reason: Viewstate was invalid.
ViewStateException information: 
    Exception message: Invalid viewstate. 
    Path: /StarterSite/Checkout/Default.aspx

This problem here is that the Checkout process uses a couple of controls that contain view/controlstate.  When creating viewstate ASP.NET ties the viewstate to the assemblies of these controls.  Each web server ends up with a different assembly because each web server does its own compilation and picks its own assembly name for the web controls.

There are a couple of options you can use to fix this:

  1. Turn on sticky load-balancing.  This means that each request from the same client will go to the same server.  The viewstate will only be unpacked by the machine that created it (except if that machine goes down and the load balancer switches to another machine -- rare but certainly possible).  Consult the documentation for your particular load balancer to determine how to configure this.
  2. Pre-compile the web site and distribute the compiled assemblies to each web server.  This ensures that all of the assemblies match and you won't hit this problem. 

To pre-compile you use the aspnet_compiler.exe utility in your .NET Framework directory.  In a nutshell you do:

D:\Inetpub\wwwroot\StarterSite>d:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_compiler.exe -v /StarterSite d:\compiletemp

Copy the files in d:\compiletemp to the virtual root of each web server in your farm.  For more information see the aspnet_compiler page and this topic on pre-compiling at MSDN.  One note, you probably don't want to use the -u switch as it may re-introduce this problem as you update the site (I'm not sure, but better safe than sorry).