Sunday, October 28, 2007

Event message: Forms authentication failed for the request. Reason: The ticket supplied has expired.

If you get this error a couple of times per hour:





Event code: 4005
Event message: Forms authentication failed for the request. Reason: The ticket supplied has expired.
Event time: 10/7/2007 2:47:36 PM
Event time (UTC): 10/7/2007 12:47:36 PM
Event ID: dc144643e473474d8cdc4ebf37f274ec
Event sequence: 501
Event occurrence: 64
Event detail code: 50202
Application information:
Application domain: /LM/W3SVC/86188572/Root/foo-4-12836d23d585972500
Trust level: Full
Application Virtual Path: /foo
Application Path: e:\foo
Machine name: hostname
Process information:
Process ID: 1324
Process name: w3wp.exe
Account name: NT AUTHORITY\NETWORK SERVICE
Request information:
Request URL: *.aspx
Request path: *.aspx
User host address: x.x.x.x
User:
Is authenticated: False
Authentication Type:
Thread account name: NT AUTHORITY\NETWORK SERVICE
Name to authenticate:
Custom event details:



Probably you have the following scenario:
- multiple websites on the same IIS
- some Asp.Net 1.0/1.1 and some 2.0
- generally happens on 1.1 root and 2.0 subdirs

Why it happens?

It's related to forms authentication. If you use ASP.Net forms authentication on some of the websites 1.1 and 2.0, authentication cookie cannot be decrypted.
That is because in older versions they used 3DES and in 2.0 microsoft uses AES(advanced encryption standard - a Rijndael 128 bits version).
Also it happens because active users that are authenticated will submit a request after the application had restarted. On restart, a new set of encryption/decryption keys are created, so 'old' users won't be able to have their auth cookie decrypted on the next request.

Yes, there is a fix, not that nice but you can use it.

Three options.

1. Extend application logout time and insert sliding expiration(sliding increases expiration time of auth cookie as of last request). Make sure session state has same expiration time as your logout time. Also increase your application pool expiration time. AND make sure your web app doesn't crash (so that it triggers a restart and a new set of keys). You'll get less 4005 messages, but still some.





forms loginurl="login.aspx" protection="all" path="/" timeout="60" slidingexpiration="true"

2. Go to machine.config and setup manually the encryption keys. The same procedure applies for managing webfarms and making sure that all clusters use the same cookie authentication decryption. For all framework versions.

3. Set it up independently per application web.config.
You should insert inside "machineKey" section of your web.config 2 keys, "validationKey" and "decryptionKey". Additionally for 2.0 applications, you should also specify the decryption algorithm "3DES". I know some of you will say that "3DES" is less powerfull than AES. But your purpouse here is to avoid migrating .net 1.0/1.1 web applications to 2.0.


I hope you'll get rid of this message.

Bye

Saturday, October 27, 2007

IIS WebGarden problem with session

Problem: You activate webgarden and define multiple w3wp.exe processes per application pool. (like in the picture with a application pool properties IIS6.0)




This is supposed (if your server has enough resources) to boost your server load capacity.

If you spot weird behaviour in your application like errors thrown randomly(null reference exceptions - Object reference not set to an instance of an object) grids paging not working as supposed to be and objects in session state being there or not, you seriously have to check what kind of session state you are using.

If you are using inproc (in process) session state, and you use Session objects in your application, you have a issue and 2 options:
either you switch back to single process in web garden or you continue reading the article.


Assuming you want performance, you want to continue with webgarden.

Why is in-proc not working?
Assuming you define 3 worker processes in a webgarden, you will have 3 distinct session states, each in its worker process. When a client makes requests to your IIS, he will be routed randomly to one of the worker process (which one is available and not busy, etc). This means that a previously object stored in session during the previous request, would not exist into this process and you'll reach weird scenarios.

It's true that Session Object should be temporary. Meaning you must always check your object existance in session before using it (to avoid nullreference errors) and load it from db or from wherever else you need to rebuild it.

But sometimes your human logic :) might not be able to build such design and you will always keep some info in session (instead you might use asp.net viewstate - which is better - in order to keep all data at client, if the data is small enough so it won't make client postbacks harder).

To be able to work with session state in 'common' you should use the next level in session state saving. Meaning ASP.Net State service or SQL state server.

For the first one, ASP.Net State service, read below.

You must start the windows service (ASP.Net State service)


and activate it by adding the following config section in application web.config:

sessionstate timeout="20" cookieless="false" sqlconnectionstring="data source=127.0.0.1;user id=sa;password=" stateconnectionstring="tcpip=127.0.0.1:42424" mode="StateServer">sessionState mode="StateServer" stateConnectionString="tcpip=127.0.0.1:42424" sqlConnectionString= "data source=127.0.0.1;user id=sa;password=" cookieless="false" timeout="20"/

This means that instead of using the session state inside each w3wp.exe process, you will use a sepparate windows service(ASP.Net State Service) for all your processes for holding state objects.
Carefull here if you want to hold BIG objects in session (bad design anyway) you might turn into performance issues due to serialization processing.

In order to use this state service, your application must be ready to accept it. Meaning you will have to have all objects needed to be put into session, serializable (objects marked as serializable with [Serializable] attribute).

Even if you try to put in session a object that is serializable but its instance contains a instance of a non serializable object, errors will occur at serialization time (when inserting the object into session, a 'cannot serialize object X' error will occur).

Changing to this state on-the-fly, for performance increase, might drive you the opposite way, so pay attention what objects you are putting into session (and they're childs).

Also, state service requires a lot of RAM. But again, the advantage of keeping the session states alive even if IIS restarts, is a tremendous improvement for your server.

As a short notice, please make sure ASP.NET State service is running (default it is stopped). Go to Control Panel, Administrative Tools, Services, Asp.Net State Service, start it and make sure its start up type is on "Automatic".

At this point, having changed the settings in web.config and your code to have serializable objects into session, you can safely use ASP.Net state service, and enable your webgarden feature.

Happy bigger load capacity.

System.CannotUnloadAppDomain

Error in Event Viewer - Application.
----
The description for Event ID 5000 from source .NET Runtime 2.0 Error Reporting cannot be found. Either the component that raises this event is not installed on your local computer or the installation is corrupted. You can install or repair the component on the local computer.
If the event originated on another computer, the display information had to be saved with the event.
The following information was included with the event:
clr20r3
w3wp.exe
6.0.3790.3959
45d6968e
system.web
2.0.0.0
4333aecd
5ce
47
system.cannotunloadappdomain
NIL
----
Possible causes:
-Server out of resources - low memory (RAM), low disk space
-Asynchronous processes unable to be terminated
-IO operations blocked (socket etc)

Why it happens:
IIS tries to recycle a w3wp.exe (due to unhealthy, deadlocked, db timeout states) and cannot unload it due to one of the above reasons. IIS then decided to kill that process in a 'brutally' way and log this kind of error.

Is it wrong?
Usually start with a few errors per day and can end into a crash at each 4 minutes if you have low hardware resources and lot of load (more than 4000 requests)

Temporary fix
Upgrade RAM, check disk space then go for webgarden and in a short time to webfarm.