ASP.NET Cookies BUG - multiple cookies duplicated randomly?

It looks like an ASP.NET cookie error is annoying when writing a response stream to a wire. Set-Cookie headers are multiplied randomly.

My example: ASP.NET MVC4 on an explicit IIS8 server, but the same problem occurs in IIS7 integrated mode, and I found messages about the same release of IIS6 back in 2009. It seems that the problem exists for a while.

For example, in Global.asax.cs I subscribe to the BeginRequest event and write in HttpResponse.Cookie in my event handler:

 public class MvcApplication : System.Web.HttpApplication { public override void Init() { base.Init(); BeginRequest += OnBeginRequest; } void OnBeginRequest(object sender, EventArgs e) { Response.Cookies.Set(new HttpCookie("OnBeginRequest", "0")); } } 

This will already display the Set-Cookie header "OnBeginRequest" twice. But, if this is done for all HttpApplication events (AuthenticateRequest, AcquireRequestState, etc. Only ~ 20 events), the header of the HTTP response sent to the browser will have many duplicates recorded. This is also evident after the writing of cookie letters begins with begging.

 HTTP/1.1 200 OK Cache-Control: private Content-Type: text/html; charset=utf-8 Server: Microsoft-IIS/7.5 Set-Cookie: OnBeginRequest=0; path=/ Set-Cookie: OnBeginRequest=0; path=/ Set-Cookie: OnAuthenticateRequest=1; path=/ Set-Cookie: OnBeginRequest=0; path=/ Set-Cookie: OnAuthenticateRequest=1; path=/ Set-Cookie: OnPostAuthenticateRequest=2; path=/ Set-Cookie: OnBeginRequest=0; path=/ Set-Cookie: OnAuthenticateRequest=1; path=/ Set-Cookie: OnPostAuthenticateRequest=2; path=/ Set-Cookie: OnAuthorizeRequest=3; path=/ Set-Cookie: OnPostAuthorizeRequest=4; path=/ Set-Cookie: OnBeginRequest=0; path=/ Set-Cookie: OnAuthenticateRequest=1; path=/ Set-Cookie: OnPostAuthenticateRequest=2; path=/ Set-Cookie: OnAuthorizeRequest=3; path=/ Set-Cookie: OnPostAuthorizeRequest=4; path=/ Set-Cookie: OnResolveRequestCache=5; path=/ Set-Cookie: OnPostResolveRequestCache=6; path=/ Set-Cookie: OnBeginRequest=0; path=/ Set-Cookie: OnAuthenticateRequest=1; path=/ Set-Cookie: OnPostAuthenticateRequest=2; path=/ Set-Cookie: OnAuthorizeRequest=3; path=/ Set-Cookie: OnPostAuthorizeRequest=4; path=/ Set-Cookie: OnResolveRequestCache=5; path=/ Set-Cookie: OnPostResolveRequestCache=6; path=/ Set-Cookie: OnMapRequestHandler=7; path=/ Set-Cookie: OnBeginRequest=0; path=/ Set-Cookie: OnAuthenticateRequest=1; path=/ Set-Cookie: OnPostAuthenticateRequest=2; path=/ Set-Cookie: OnAuthorizeRequest=3; path=/ Set-Cookie: OnPostAuthorizeRequest=4; path=/ Set-Cookie: OnResolveRequestCache=5; path=/ Set-Cookie: OnPostResolveRequestCache=6; path=/ Set-Cookie: OnMapRequestHandler=7; path=/ Set-Cookie: OnPostMapRequestHandler=8; path=/ Set-Cookie: OnAcquireRequestState=9; path=/ Set-Cookie: OnPostAcquireRequestState=10; path=/ Set-Cookie: OnPreRequestHandlerExecute=11; path=/ X-AspNetMvc-Version: 4.0 X-AspNet-Version: 4.0.30319 Set-Cookie: OnBeginRequest=0; path=/ Set-Cookie: OnAuthenticateRequest=1; path=/ Set-Cookie: OnPostAuthenticateRequest=2; path=/ Set-Cookie: OnAuthorizeRequest=3; path=/ Set-Cookie: OnPostAuthorizeRequest=4; path=/ Set-Cookie: OnResolveRequestCache=5; path=/ Set-Cookie: OnPostResolveRequestCache=6; path=/ Set-Cookie: OnMapRequestHandler=7; path=/ Set-Cookie: OnPostMapRequestHandler=8; path=/ Set-Cookie: OnAcquireRequestState=9; path=/ Set-Cookie: OnPostAcquireRequestState=10; path=/ Set-Cookie: OnPreRequestHandlerExecute=11; path=/ Set-Cookie: OnPostRequestHandlerExecute=12; path=/ Set-Cookie: OnReleaseRequestState=13; path=/ Set-Cookie: OnPostReleaseRequestState=14; path=/ Set-Cookie: OnBeginRequest=0; path=/ Set-Cookie: OnAuthenticateRequest=1; path=/ Set-Cookie: OnPostAuthenticateRequest=2; path=/ Set-Cookie: OnAuthorizeRequest=3; path=/ Set-Cookie: OnPostAuthorizeRequest=4; path=/ Set-Cookie: OnResolveRequestCache=5; path=/ Set-Cookie: OnPostResolveRequestCache=6; path=/ Set-Cookie: OnMapRequestHandler=7; path=/ Set-Cookie: OnPostMapRequestHandler=8; path=/ Set-Cookie: OnAcquireRequestState=9; path=/ Set-Cookie: OnPostAcquireRequestState=10; path=/ Set-Cookie: OnPreRequestHandlerExecute=11; path=/ Set-Cookie: OnPostRequestHandlerExecute=12; path=/ Set-Cookie: OnReleaseRequestState=13; path=/ Set-Cookie: OnPostReleaseRequestState=14; path=/ Set-Cookie: OnUpdateRequestCache=15; path=/ Set-Cookie: OnPostUpdateRequestCache=16; path=/ Set-Cookie: OnLogRequest=17; path=/ Set-Cookie: OnPostLogRequest=18; path=/ Set-Cookie: OnEndRequest=19; path=/ Set-Cookie: OnBeginRequest=0; path=/ Set-Cookie: OnAuthenticateRequest=1; path=/ Set-Cookie: OnPostAuthenticateRequest=2; path=/ Set-Cookie: OnAuthorizeRequest=3; path=/ Set-Cookie: OnPostAuthorizeRequest=4; path=/ Set-Cookie: OnResolveRequestCache=5; path=/ Set-Cookie: OnPostResolveRequestCache=6; path=/ Set-Cookie: OnMapRequestHandler=7; path=/ Set-Cookie: OnPostMapRequestHandler=8; path=/ Set-Cookie: OnAcquireRequestState=9; path=/ Set-Cookie: OnPostAcquireRequestState=10; path=/ Set-Cookie: OnPreRequestHandlerExecute=11; path=/ Set-Cookie: OnPostRequestHandlerExecute=12; path=/ Set-Cookie: OnReleaseRequestState=13; path=/ Set-Cookie: OnPostReleaseRequestState=14; path=/ Set-Cookie: OnUpdateRequestCache=15; path=/ Set-Cookie: OnPostUpdateRequestCache=16; path=/ Set-Cookie: OnLogRequest=17; path=/ Set-Cookie: OnPostLogRequest=18; path=/ Set-Cookie: OnEndRequest=19; path=/ Set-Cookie: OnPreSendRequestContent=20; path=/ Set-Cookie: OnPreSendRequestHeaders=21; path=/ X-Powered-By: ASP.NET Date: Mon, 20 May 2013 10:47:20 GMT Content-Length: 4002 

Even worse, if the same cookie is written in 1 event handler and then updated in another, duplicates with different values ​​will be displayed in the header.

Are there any settings or workarounds that can prevent this default behavior of the HttpResponse.Cookies collection?

+9
source share
4 answers

The error affecting IIS 7 is probably not the same as IIS6. This bug has been fixed since 4.7, it has the following identifier: DevID 289778 .

Background

Here is a description of it: In IIS7, every time you leave the asp.net pipeline to return to the IIS pipeline, cookie headers are added if necessary. In integrated mode, you leave the asp.net pipeline between most events.

Therefore, when he writes down cookies as necessary, he checks to see if any cookies have been deleted. If not, it checks if cookies have been added. If so, he adds a header for this cookie. It also checks if any cookies have been changed. If so, he adds a headline for him. Although it iterates cookies, it records everything that has been changed.

If any cookies were deleted or any were changed, then it deletes all Set-Cookie headers and writes a new set. (Or at least he is trying. If the headers were reset, then obviously this is not possible.)

So far, so good. However, upon re-entering the managed pipeline, we read all the response headers back and restore the response cookies. This is necessary because some unmanaged modules may add new response cookies. However, it does not set the add flag for any cookies copied from response headers. So for now, all is well, right?

Bug

Well, not quite. Each time a cookie is added (or removed from) the Response.Cookies collection, the Request.Cookies collection Request.Cookies completely reloaded and then response cookies are added to it, setting the HttpCookie flag of the HttpCookie object HttpCookie . This is mistake. This causes the β€œAdded” flag to be set for each response cookie each time each cookie is added or deleted.

This means that if you do not change or delete cookies, but add at least one cookie, all cookies previously added at other stages of the pipeline will be duplicated. However, if you change a cookie or delete a cookie from the Response.Cookies collection, then you will delete all duplicates that previously occurred.

Hackish Workaround

To work around this error, simply add and delete some arbitrary cookie or change the cookie during the same event that the headers are written. Usually it will be EndRequest , unless you use Server.Transfer , Server.Redirect , Response.Flush or Reponse.End (unless you set the endReponse parameter to false) anywhere in the application, in which case you should do this is the same event that is happening. Also, do not forget about any incidents in the libraries or about the Http modules you use. Essentially, you just want to add the following code for each individual event:

 try{ var guid=Guid.NewGuid(); context.Response.Cookies.Add(new HttpCookie(guid.ToString(),string.Empty); context.Response.Cookies.Remove(guid.ToString()); } catch(HttpException) { //This means the headers were already written, //in which case we need not do anything. } 
+5
source

Another duplicate cookie error description:
Context: Web Forms application (using form authentication and URL rewriting)
Problem: A session cookie is systematically sent twice (except for the first request received after compiling the application).
Platform: IIS 10 / .NET Framework 4.7.2

Kevin's solution really works on this error (too).

Notes:
There is no need for a random cookie name.
On the asp.net web forms page, this workaround can be used for the Load event.

0
source

When you set a value in a cookie, first clear it, .Clear()

 var cookie = this.Request.Cookies.Get("MyCookie"); if (cookie == null) { cookie = new HttpCookie("MyCookie"); this.Response.Cookies.Add(cookie); } else { cookie.Values.Clear(); //crear firstly.. cookie.Values.Add("AnyKey", "AnyValue"); } 
-one
source

If you move between pages after changing the cookie value without returning to the client (server.Transfer), the cookies will be duplicated.

-one
source

All Articles