Getting ViewStateException: Invalid viewstate while Machine keys are the same - asp.net

I have 8 host behind LB and all of them are single process(not web garden). Despite setting all of them with the same machine key from iis as shown below, I'm still getting Invalid viewstate exception rarely.
There similar questions but none of them helped me(I've no server with pending updates or restart as in the other questions or i'm not using server.execute etc). So please don't flag as duplicate. Are there any alternative ways to prevent this exception?
Thx

Normally, This is because of the difference in Machine keys in different servers. We use Web Farm for High availability. In this case, if a Client sends a request then the Load balancer decides, which webserver to serve the request. It happens several times that another request might be served by another server. So here is the issue.
As we know, view stat is Client-side state management techniques and the data travels with the request and response. So if the view state is encrypted with some machine key and in other requests if handled by another server and that has different machine key, it would not be able to decrypt it and will through the error.
Every server generates a new key when it is set auto. and even sometimes any recycle of the app domain will generate a new key when it is set to auto. It means we cannot use the default auto-generated key. So here the solution is to use a specific key in the machine.config to prevent automatic key generation on each process start.
One another flexible approach, however, would be to add a MachineKey section to the web.config file of your web site. This would not require to make the changes on every web server.
another way is you could try to set below code in machine.config:
enableViewStateMac="false"

Related

IIS 7.5 Load Balancing--do Sessions stick to the originating server?

Apologies if there is an answer already out here but I've looked at over 2 dozen threads and can't find the specific answer.
So, for our ASP.NET (2.0) application, our infrastructure team set up a load balancer machine that has two IIS 7.5 servers.
We have a network file server where the single copy of the application files reside. I know very little about the inner workings of load-balancing and even IIS in general.
My question is regarding sessions. I guess I'm wondering if the 'balancing' part is based on sessions or on individual page requests.
For example, when a user first logs in to the site, he's authenticated (forms), but then while he navigates around from page to page--does IIS 7.5 automatically "lock him in" to the particular server that first logged him in and authenticated him, or could his page requests alternate from one server to the next?
If the requests do indeed alternate, what problems might I face? I've read a bit about duplicating the MachineKey, but we have done nothing in web.config regarding MachineKey--it does not exist there at all.
I will add that we are not experiencing any issues (that we know of anyway) regarding authentication, session objects, etc. - the site is working very well, the question is more academic, and I just want to make sure I'm not missing something that may bite me down the road.
Thanks,
Jim
while he navigates around from page to page--does IIS 7.5 automatically "lock him in" to the particular server that first logged him in and authenticated him
That depends on the configuration of the load balancer and is beyond the scope of a single IIS. Since you haven't provided any information on what actual balancer you use, I can only provide a general information - regardless of the balancer type (hardware, software), it can be configured for so called "sticky sessions". In such mode, you are guaranteed that once a browser establishes connection to your cluster, it will always hit the same server. There are two example techniques - in first, the balancer just creates a virtual mapping from source IP addresses to cluster node numbers (which means that multiple requests from the same IP hit the same server), in second - the balancer attaches an additional HTTP cookie/header that allows it to recognize the same client and direct it to the same node.
Note that the term "session" has nothing to do with the server side "session" where you have a per-user container. Session here means "client side session", a single browser on a single operating system and a series of request-replies from it to your server.
If the requests do indeed alternate, what problems might I face
Multiple issues. First, encryption, if relies on machine key, will not work. This means that even forms cookies would be rejected by cluster nodes other than the one that issued the cookie. A solution is to have the same machine key on all nodes.
Another common issue would be the inproc session provider - any data stored in the memory of one application server will not "magically" appear on other cluster nodes, thus, making the session data unavailable. A solution is to configure the session to be stored in a separate process, for example in a sql server database.
I will add that we are not experiencing any issues (that we know of anyway) regarding authentication, session objects
Sounds like a positive coincidence or the infrastructure team has already configured sticky sessions. The latter sounds possible, the configuration is usually obvious and easy.

Validation of viewstate MAC failed caused due to Application Pool Idle Timeout

i had bought a web domain online where i am hosting asp.net website's/web-application's.
Many a times I am facing an error:
Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster......
After a long research i had found that the error occurs due to "Application Pool Idle Timeout".
By default an app-pool will recycle every 5 minutes. If this recycle happened while a user is busy on the site and send post back to the server, the server no longer recognizes the session/viewstate and rejects what is being posted back.
My "Application Pool Idle Timeout" value is around 5 min. which is too short.
i had contacted the domain person to change the timeout period but they refused to do so saying its same for all and cant be changed.
I had googled for other solutions and found the below solutions:
Setting the EnableViewStateMAC property to false (Not good w.r.t. security reasons).
Provide your own validation and decryption keys "" (Doesn't work).
Please provide me a better solution ASAP.
Or Should I change the domain manager (like godaddy.com).
I have seen and resolved this issue in past. This issue majorly comes when you host application on Web Farm or web Cluster.
When a page is rendered, its view state is encrypted on server and sent to client. When page is posted back, this view state data is decrypted on server to get the state of the page. For Encryption and decryption of viewState server uses some keys, which if not provided in Maching.config files, are generated on the fly by server.
If you are on a single server hosting environment, these keys might get recycled. But on a Web Farm or Web Cluster, if these keys are generated at random then they are different for every server, and a request from one server can be posted back to another server that has different set of key and where it fails.
Solution to this is Adding MachineKey entries to all the server's Machine.Config files, or to your application's web.config files so that each server uses same keys for encryption and decryption of view state.

Avoiding invalid viewstate when deploying on a load balanced website without downtime

Here is the scenario:
We have 3 web servers A, B, C.
We want to release a new version of the application without taking the application down
(e.g. not using the "Down for maintenance page").
Server A goes live with latest code.
Server B gets taken off-line. Users on Server B get routed to A and C.
Page1.aspx was updated with new control. Anyone that came from Server B to Server A while
on this page will get a viewstate error when they perform an action on this page. This is what we want to prevent.
How do some of you resolve this issue?
Here are some thoughts we had (whether it's possible or not using our load balancer, I don't know... I am not familiar with load balancer configuration [it's an F5]):
The more naive approach:
Take down servers A and B and update. C retains the old code. All traffic will be directed to C, and that's ok since it's the old code. When A and B go live with the update, if possible tell the load balancer to only keep people with active sessions on C and all new sessions get initiated on A and B. The problem with this approach is that in theory sessions can stick around for a long time if the user keeps using the application.
The less naive approach:
Similar to the naive approach, except (if possible) we tell the load balancer about "safe" pages, which are pages that were not changed. When the user eventually ends up on a "safe" page, he or she gets routed to server A or B. In theory the user may never land on one of these pages, but this approach is a little less risky (but requires more work).
I assume that your load balancer is directing individual users back to the same server in the web farm during normal operations, which is why you do not normally experience this issue, but only when you start redirecting users between servers.
If that assumption is correct then it is likely the issue is a inconsistent machinekey across the server farm.
ViewState is hashed against the machine key of the server to prevent tampering by the user on the client side. The machine key is generated automatically by IIS, and will change every time the server restarts or is reset, as well as being unique to each server.
In order to ensure that you don't hit viewstate validation issues when users move between servers there are two possible courses of action.
Disable the anti-tampering protection on the individual page or globally in the pages element of the web.config file using the enableViewStateMac attribute with a false value. I mention this purely for the sake of completeness - you should never do this on a production website.
Manually generate a machine key and share that same value across each application (you could use the same key for all your applications, but it is sensible to use one key per application to maximise security), on each of your servers. To do this you need to generate keys (do not use any you may see in demos on the internet, this defeats the purpose of the unique machine key), this can be done programatically or in IIS manager (see http://www.codeproject.com/Articles/221889/How-to-Generate-Machine-Key-in-IIS7). Use the same machine key when deploying the website to all of your servers.
I can't answer on the best practice for upgrading applications that require 100% uptime.

Validation of viewstate MAC failed when on page for 20+ minutes

If you open a web page on one of the websites hosted on our server, leave it for 20 minutes and then submit a form, a Validation of viewstate MAC failed. error occurs.
What possible reasons could there be for this?
There's a few reasons this can happen:
Auto-Generated Machine Keys:
If your application pools have the default idle timeout of 20 minutes AND you're using auto-generated validation and decryption keys then each time the pool starts it will generate a new set of keys. This invalidates the browser's encrypted viewstate. You'll also find that forms authentication tickets for persistent tickets will also become invalid.
To overcome this set these keys to fixed values in:
`c:\%systemroot%\microsoft.net\framework\v2.0.50727\CONFIG\machine.config`
You need to add the <machineKey> configuration element to the <system.web> section. There's a pretty good article here that explains how to do this:
How To: Configure MachineKey in ASP.NET 2.0
Scroll down to the section on "Web Farm Deployment Considerations" and Generate Cryptographically Random Keys.
If you're running a load balanced web farm you also need to set each server's machine key to exactly the same value.
Incorrect form action value (3.5SP1):
There's also a case (post 3.5SP1) where if you set the action attribute of your ASP.NET form to something other than the page being posted back to and you're not using crosspage postbacks then you will get this error. But you'd see this right away:
Validation of viewstate MAC failed after installing .NET 3.5 SP1
Timing/Long Running Pages:
There's also an edge case for pages that take a long time to render where if the page is partially rendered and a postback occurs:
Validation of viewstate MAC failed error
Root Cause This exception appears because Controls using DataKeyNames
require Viewstate to be encrypted.
When Viewstate is encrypted (Default
mode, Auto, is to encrypt if controls
require that, otherwise not), Page
adds
field just before closing of the
tag. But this hidden field
might not have been rendered to the
browser with long-running pages, and
if you make a postback before it does,
the browser initiates postback without
this field (in form post collection).
End result is that if this field is
omitted on postback, the page doesn't
know that Viewstate is encrypted and
causes the aforementioned Exception.
I.E. page expects to be fully-loaded
before you make a postback.
It's taken us a while to find the answer to this as I had been informed that another IIS7 server I was comparing it to had been setup in the same way, by the same person.
It turns out the server with the websites which were receiving this error had been setup using Plesk, whereas the other server had not been.
It seems Plesk sets the Idle-Timeout to 5 minutes on the application pools, which is what was causing this error.
To change this do the following:
Open IIS
Click on application pools node
Locate your web application's application pool
Right-Click and select Advanace Settings
Set the Idle Time-out(minutes) property to 0 or increase it to 30+ minutes
For me, this solved the problem:
I've set LoadUserProfile = True in the application pool to make HKCU registry hive be available to the application.
Note: This is compatible with IIS 7.0+
I ran into this problem, and the scenario was a single web server hosting a very basic ASP.Net application. After struggling a lot I found this post, and that helped me to understand that the problem was the worker process getting recycled.
I find this quite harsh, as it's a scenario that an application might face and such a core error prevents you to handle it properly. As far I could see, this is originated because the default configuration for handling this keys will use the machine.config that states that keys are automatically generated and isolated per application. I think in this cases ASP.Net a temporary key and store it at the worker process level, and when that worker process is gone the issue arises and can't be handled.
The alternative of configuring the machine key solves the problem, clearly is better to set it on the web.config file rather the whole machine.config to keep it at the lowest granularity level.
Another option is to disable the view state MAC check, also through web.config. It will depend on the security level of your application and the risk of having the view state tampered with.
And the best option is to avoid using view state with a MVC application.
Validation of viewstate MAC failed. If this application is hosted by a Web Farm or cluster, ensure that configuration specifies the same validationKey and validation algorithm. AutoGenerate cannot be used in a cluster
As I found out, there was a <base ....
tag in header part of my master page, that I added in last tie and before publishing. This tag specify a default URL and a default target for all links on a page. This was the main cause of the fault, this time.

asp.net: moving from session variables to cookies

My forms are losing session variables on shared hosting very quickly (webhost4life), and I think I want to replace them with cookies. Does the following look reasonable for tracking an ID from form to form:
if(Request.Cookies["currentForm"] == null)
return;
projectID = new Guid(Request.Cookies["currentForm"]["selectedProjectID"]);
Response.Cookies["currentForm"]["selectedProjectID"] = Request.Cookies["currentForm"]["selectedProjectID"];
Note that I am setting the Response cookie in all the forms after I read the Request cookie. Is this necessary? Do the Request cookies copy to the Response automatically?
I'm setting no properties on the cookies and create them this way:
Response.Cookies["currentForm"]["selectedProjectID"] = someGuid.ToString();
The intention is that these are temporary header cookies, not persisted on the client any longer than the browser session. I ask this since I don't often write websites.
Before changing any code, I would investigate why session variables are disappearing.
Perhaps it is as simple as changing the timeout setting in the web.config?
Here's a list of the session state settings in the config file: Session Element on MSDN
====================================================
Oh yeah, one other thing to try in relation to your comment:
If my memory serves me, we had some issues in the past when deploying to a web garden/farm where multiple web sites on the same server would "clash". To get round this we explicitly names the cookie as so:
<authentication mode="Forms" >
<forms loginUrl="your-login-page.aspx"
cookieless="AutoDetect"
name=".A-NAME-WHICH-IS-UNIQUE" />
</authentication>
Name: Optional attribute.
Specifies the HTTP cookie to use for authentication. If multiple applications are running on a single server and each application requires a unique cookie, you must configure the cookie name in each Web.config file for each application.
The default is ".ASPXAUTH".
From here link text
No you do not have to keep resetting the cookie in the response.
Once set that cookie will continue to be sent with each subsquent request.
However I agree with Dominic you should first determine the reason you are unable to maintain the session in the first place.
Some reasons are:-
The host is using a web garden or a load balancer that does not support session affiliation
There is an aggressive setting for session timeout on the host
The host has a problem and is recycling the application pool frequently
Your client has overly tight cookie settings and is rejecting all cookies (however that would mean your alternative solution wouldn't work either)
Application logic may be faulty causing Session.Abandon or Session.Clear when it ought not.
In answer to your question about copying the cookie from the request to the response, no this is not necessary.
When the cookie is created it can persist for as long as you require.
If it is just needed for the duration of the session then do not set anything against the Expires property. In this case the cookie will be held in the browser memory and served up with each request to you website until the browser is closed.
If it is to persist between sessions the set the appropriate DateTime value against the Expires property. In this case the cookie is written as a file on the client machine and continue to be served up with each request to your website until it's exiry date is reached or it is deleted.
Of course, be aware clients can disble cookies in their browser.
I do agree with previous answer, that you should investigate the sessions timing out first!
But regarding cookies:
Request cookies are the cookies sent from the client to the server and Response cookies are the ones sent from server, telling the client to save them locally and attach them to the next, and all upcoming until the cookie is outdated, requests to the server.
Cookies have a limit on size and because of their behavior will create an overhead on data sent between server and client on requests, and can of course also be disabled on client side as well.
I would suspect that the reason you might be loosing session variables is that your application is running in a web garden. This means two or more processes are running your application.
In your web.config there should be sessionState tag. If mode="InProc" then try setting mode="StateServer". This will cause all the processeses hosting your application to use the session state server to store the session state elements. Also check the timeout as was mentioned previously.
The research I've done into cookies suggests they would not be a desirable alternative to session variables. Browsers enforce arbitrary limits on the number of cookies that can exist at any one time as well as the number per site. They are also prone to being dropped randomly.
You can enable cookieless sessions. There are some potential issues but it might work for your site.
I was a webhost4life customer up until two months ago, the issue I was experiencing was the application pool being recycled frequently - probably because the host had some kind of problem. In the end I moved to a VPS and never looked back (not a webhost4life VPS either).
For Sharing hosting the best approach is to use SQL Session State.
It's a little bit slower but much more reliable.
I had the same problems back in the days and my Memory Sessions were always getting erased, this happends because someone on the same hosting environment didn't know how to accomplish stings and IIS just reset the Application Pool, or it could even do by Auto Refresh the AppPool from the Hosting point of View (so no website will hang).
Since I started to use SQL State ... I just must say WOW!
you have total control in everything, even set the timeout (Memory Sessions are set by the machine config and no matter what you set in code or web config you will never override that setting)
and you gain something new, if you change the code, you users will not need to left the website to re.login again as they will continue from their existing session.
Setting it up it's fairly easy and you have a ton of examples on how to accomplish such behavior.
no matter what you do, DO NOT GO to cookies as they are not reliable!
You might consider using this little library:
http://www.codeproject.com/KB/aspnet/Univar.aspx
It can automatically switch to the session whenever the cookie is unavailable. It also has a server side implementation of the cookie whereby all cookies are stored on the server and asp.net authentification can be used to identify the user.

Resources