Session_Start firing multiple times on default ASP.NET MVC3 project - asp.net

I think I may have found a problem with ASP.NET MVC and it's event pipeline. In particular, I am finding that Session_Start is being called multiple times, each containing a new SessionID.
Here's the step-by-step process:
Open VS2010
File | New Project
ASP.NET MVC 3 Web Application, accept default name, click OK
Select Internet Application (although I don't think it matters really), click OK
When finished creating, edit the Global.asax.cs file
Add the following method (yes it's empty):
protected void Session_Start()
{
}
Set a breakpoint in the method
Debug
Notice that the breakpoint is caught twice before displaying the page. If you watch "Session.SessionID" when the breakpoints are caught, you will see that the session id is new each time.
Once you get to the home page, click on the "Home" or "About" tab link.
Session_Start will be fired again, this time with a new SessionID.
Continue execution, and any subsequent actions will no longer fire Session_Start.
I tried the same thing on a standard ASP.NET Web Application (not MVC), and Session_Start only fired once.
I'm pretty sure I'm not doing something wrong here, as I am using the default project templates, and the only code that is being modified is the Global.asax.cs file, to add the Session_Start method.
I am using IIS Express, but I've repeated the above steps using the "Cassini" web server (Visual Studio Development Server), with the same result.
Any advice?
UPDATE
I decided to use Fiddler to inspect the HTTP traffic during my debug session. It seems that:
The first Session_Start is fired when I am requesting the "/" URL. This seems reasonable. The SessionID generated at that time is then written in the response to the browser. Again, seems reasonable.
Fiddler then shows requests/responses for the *.js and *.css files. All successes. None of those fire off Session_Start. Good so far.
Then Fiddler shows that a request has been made for "/favicon.ico". At this time, Session_Start fires, and generates a new SessionID... I continue.
On Fiddler, it shows that the "/favicon.ico" file was not found (404). The webpage is displayed. I click on the "Home" link.
The URL "/" is requested and response is OK in Fiddler. But then, another "/favicon.ico" file is requested, and again Session_Start fires with a new SessionID... I continue.
All subsequent requests have responses, and the browser stops asking for "/favicon.ico".
I made note of each of the three SessionID's generated, and it seems the one that the browser holds on to is the first one. So when we get to step 6 above, and everything seems to work, it's actually using the very first SessionID that was generated.
So... I decided to host a "favicon.ico" file. I placed the ico file in the root of the project, and started my debug session again. This time, Session_Start only fires once. "/favicon.ico" was served successfully (200).
So... I guess it is working the way it should in a sense... But why do calls to "/favicon.ico" fire off the Session_Start event???? Shouldn't I have the choice to NOT host a favicon?
ASIDE: I tried all the above in an ASP.NET (not mvc) project, and it did not have the same problem, even though there was no favicon.ico file hosted by a default "ASP.NET Web Application" project.

I kinda had this problem for a while, and finally I realised that it was because there was some http/https shenanigans going on... looks like it destroys and recreates your session if you flip the ssl around like that and you have
<sessionState mode="InProc" sqlCommandTimeout="3600" timeout="120" cookieless="false" />
<httpCookies httpOnlyCookies="true" requireSSL="true" />
Possibly a trap for new players or people who are really tired and not paying attention! :)
Just FYI in case this helps anyone...

I think I've come to a point where I have a couple of solutions (albeit both seem 'hacky' to me), so I think I'll accept these and move on.
Got a comment from #Tz_ above that mentioned I should ignore the route for the favicon file. That's essentially what I'll be doing. (kudos #Tz_!)
Came across the following post, (among others). It describes a problem that when the browser requests a "/favicon.ico" file from an ASP.NET MVC site, the MVC stack is mistakingly trying to look for and instantiate a controller. I'm wasn't sure if that was true or not for my situation, but the answer suggested adding the following route entry:
routes.IgnoreRoute("favicon.ico");
I gave it a shot (added the above), and that fixed it!
So, I still don't know why "/favicon.ico" request has a mistaken identity in MVC, but I know how to fix it in my situation. Either:
Host a favicon,
or add an ignore route entry.
Again, both seem like hacks to me, as I think this is something controller factories should be capable of handling gracefully. IMHO

Reason you are getting Session_Start firing each time is because you have <httpCookies requireSSL="true" /> in <system.web> in your Web.Config remove this and you are good to go.

I can't reproduce this problem. I've tested on ASP.NET MVC 3/Tool Update, Win08/R2/SP1 and Win7/SP1 using IIS 7.5, Cassini and IIS Express. I see the 404 favicon request in Fiddler, but the break point is not hit for favicon. I tested with IE9, the current FF and Chrome. Each time I hit the site with a new browser, Session_Start() is called and I see the new session ID. I work for Microsoft so I'd like to know how to reproduce this problem.

This happened to me when I had some <img> in my pages with a wrong "src" attribute. Putting a valid path in "src" solved my problem.

Related

Session being reset inadvertently

I have a legacy ASP.NET application. It was converted from NET 2 to net 4.
It uses state server session.
At some point, the app opens a new page (in a new browser tab: link target = "_blank")
But after returning to calling page (tab), I discovered the session is reset, so current user is no longer used and app redirects to login page. Actually, SessionID remains unchanged, but IsSessionNew is set to true, and session has no variables set in it.
The app doesn't use Session.Abort or Session.Clear.
Even if I change session to InProc, and change the target for the links to _top, or _self, or remove entirely, the same thing happens - session got reset.
This is session setting in web.config (alternatively I used StateServer, but with same result)
<sessionState timeout="432000" cookieless="UseCookies" mode="InProc"/>
Any idea what can cause this?
Thank you.
I finally fixed the problem.
However, I didn't found the actual cause, but I found the module which caused the issue.
It was a aspx page which did 1001 things (it's basic functionality plus another approximatively 80 other things based on ajax calls (!!!). I didn't made that page !!!
But the part that caused the problem was a functionality that served an image file.
So I rewrite that part as an ASHX handler, and then the code worked ok - the session remained open.

"Validation of viewstate MAC failed. If this application is hosted by a Web Far..."

i am facing the dreaded:
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.
Error.
Ok so i looking it up and found that it can be caused by two things, viewState which can not be verified by the page, and/or events that can not be validated.
I put
<pages enableEventValidation="false" enableViewStateMac="false" viewStateEncryptionMode="Never">
In my web.config to stop the problem, but that hardly seems like a fix to me.
The thing is, i never even used viewState in my application. I know that asp.net uses viewstate by default to store some things, but i doubt the default values stored here will cause any errors.
I noticed that the problem seems to happen when i postBack and the page has not finished loading yet.
Thanks
Edit: Please, can someone test my website www.vittoriosaStarsNursery.com and see if you get the error i got above? I dont get it locally but people keep telling me they are getting it.
Isnt this just a case of putting a one liner in your web.config
<machineKey decryptionKey="A4B12CCDD50E95F8GB9GFH6JKAT4Y0U0I2OF2DF2AAFE5AB46189C,IsolateApps" validation="AES" validationKey="480CDF2AS9S9AS5CFDGF0GHFH9JJH4KHKAKLJ2L9F3SAS82A6C16911A29EF48903783F94529C21570AACB72766FB38CD4CE7B85B0ACE3149DC5FC1CCF1AA1CECE3579659996593B06,IsolateApps"/>
One thing I have come across that causes this issue has to do with the recycling intervals of the app-pools on the webserver.
I found this by looking at the event information in Eventviewer/Application logs and the "Task Category" called "Web Event". Then for the time period that this event took place I looked to see if there were any recycled events that took place just before that (Eventviewer/System logs and the "Source" called "WAS".
By default an app-pool will recycle every 1740 minutes (29 hours). 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.
To overcome this from our perspective is to set the recycle event to happen at a specific time of the day when we don't expect activity on the site. In our case 3am in the morning.
Hope that helps someone out there.
You're not going to like my answer. This error is basically unavoidable in webforms. My solution was to leave webforms for MVC3 and razor.
I noticed that the problem seems to happen when i postBack and the
page has not finished loading yet.
this is one of the easiest ways to cause this error. In ASP.NET 3.5 (or 4.0) there's a setting that you can make sure viewstate gets loaded very early in the page to try to help diminish it. It still doesn't solve it.
Chunking the viewstate doesn't solve it.
There is just something inherently wrong to the way webforms works that this error will plague your application at random times forever.
At my site, this meta tag were causing the error:
<base href="http://www.SITEURL.COM" />
I have a dropdown, I update on another dropdowns changed selection. So when the postback happened (dropdown #2 changed index), I got the exception.
I've tried everything else from applying machinekey to web.config and setting theese attributes at the page
EnableViewState="false" EnableViewStateMac="false"
I am using VS 2010 against a Windows Web Server 2008 and what I eventually found was that I had two keys set for the same service in the appSettings section of webconfig. I went to IIS and checked the Application Settings on the virtual directory and got an error, fixed it in the WebConfig and the problem resolved. I did create a machine key but that did not fix the problem. Nor did the
pages (...) validateRequest="false" enableEventValidation="false"
enableViewStateMac="false" viewStateEncryptionMode ="Never"/
Settings. FWIW ...
I used this Microsoft article to create my own machineKey validationkey and decryptionKey. As others have stated, this can be placed within the system.web section of web.config, though there are security concerns if other people get hold of the key.
Well, yes i suppose disabling encrypted viewstate solves the problem but i have never tested it nor do I advise it. Viewstate stores the state of controls and is also very convenient for storing persistent variables.
Take for example you work for a garage and have a list of jobs. You go to a page that lists the jobs. Now you click a job which goes to another page appending the jobid (eg. job.aspx?id=1). On that page, there is a checkbox which marks the job as complete. Once you tick that checkbox, it posts data back to same page and writes to the database that the job is complete. But how does the server know which job to mark as complete because you have only posted back true or false from the checkbox. However, if the first time you load the job details page you record the job id in Viewstate, then when you post pack the checkbox, you can read in the jobid from the viewstate.
Why is it not good to use unencrypted viewstate?
Imagine what the server has to do to mark the job as complete. It probably has to run an sql command to update the database. Something like UPDATE jobs SET completed=GETDATE() WHERE id=1.
If your viewstate wasnt encrypted and i could add my own job id, I would put something like '; DELETE FROM jobs;' which would then cancel out the initial UPDATE command and delete ALL your jobs... not very good for the garage :)

Global.asax not firing for .aspx pages in IIS7

We run a link redirection service which can handle links thrown at it in various formats. One of these formats is to append the destination URL to the end of the link, for example
http://url.fwd/abcd/http://www.mydomain.com/page.aspx
This was working on a Windows Server 2003 / IIS6 box for the last two years, but now we're trying to move to a Windows Server 2008 / IIS7 setup and its not working anymore.
I've read about the problem with colons in the URL but it doesn't affect pages not ending in '.aspx'. For instance,
http://url.fwd/abcd/http://www.mydomain.com/page.php
would redirect fine.
http://url.fwd/abcd/http//www.mydomain.com/page.aspx
also works fine (note the lack of a second colon). Despite being the wrong URL, it does get handled by our URL forwarding system, which uses a custom 404 page. On the old system, we had a similar problem, so a method was written in Global.asax > Application_Error specifically to handle the '.aspx' case, and it worked fine.
On our new server, the Application_Error never gets thrown in Global.asax. Instead, I get a System.NotSupportedException - "The given path's format is not supported". This System.NotSupportedException is the exact case we handle in the Global.asax page, so it's definitely not being fired.
I've changed the registry keys indicated in several forum posts,
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET VerificationCompatibility=1
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\HTTP|Parameters AllowRestrictedChars=1
I've tried changing the Handler Mappings settings for .aspx.
I've tried setting the App pool to use classic mode instead of integrated, but this causes a completely different error where static content such as images and CSS do not display at all. I've checked that static content is enabled in the windows features, and it is.
Under classic mode, the '.aspx' request throws two Bad Request errors with absolutely no information whatsoever. The code of the error page I get is literally
Bad Request<html><body>Bad Request</body></html>
UPDATE: I've changed the static file Handler Mapping to the form found in this page
http://improve.dk/blog/2006/12/11/making-url-rewriting-on-iis7-work-like-iis6
However, as the author rightly points out, this is a hack and not the correct way of doing things under IIS7. It also only fixes the static file problem in classic mode. '.aspx' pages still throw an error under classic mode.
Any thoughts or input would be greatly appreciated at this point.
IIS 7 Solution
The easy solution in IIS 7 is to add a setting in your web.config file to tell IIS to process all requests through your Global.asax events. Just add or change this section in your web.config to enable requests:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" />
</system.webServer>
In my case, I was publish my site in production and I miss copy to server App_global.asax.compiled file. For this reason was not fire the Events inside Global.asax.
Hope anyelse help this tips, I lost 8 hours seeking.

Why doesn't my page have session state when called as the default document of a directory?

If I access my page like this...
/folder/default.aspx
...everything is fine. If I access it like this...
/folder/
...the page has no session state. Any ideas why?
This changed from IIS6 to IIS7, incidentally. In IIS6, it was fine. The "Default Document" feature in IIS7 is enabled, set to "default.aspx".
This is quite a mystery. One way you could try to discover the source of the problem would be to set breakpoints at several events in Global.asax and in the .aspx page. You'll have to write the code to create the event handler. Then, put some code in there to examine, for example, whether Session is null. Finally, step through and see if you can identify where the two URLs differ in behavior.
Events that I would start with include Application_Start, Session_Start, and especially Application_BeginRequest and Application_AcquireRequestState. There are other events interleaved in there that you might want to add once you've narrowed it down.

ASP.NET Routing - Do Custom Routes COMPLETELY SKIP Everything in the Global.asax?

I have a simple ASP.NET 3.5 SP1 Web Forms app... I've added the System.Web.Routing DLL, and I've made a simple route that returns a standard ASP.NET Page as the "IHttpHandler".
All is good... except that HttpContext.Current.User is null ???
So, I did a little more digging (I put breakpoints in all the events in the Global.asax file). Normally, these breakpoints get hit (when I navigate to a standard ".aspx" page):
Application_BeginRequest
Application_AuthenticateRequest
Application_EndRequest
But, when using ASP.NET Routing... none of those events are firing. Am I missing something?
Assuming you're using IIS6, the alternative is to define a "wild card" extension handler. Adding this simple "catch all" mapping to IIS6 will enable it to process your extensionless requests. By default, the .NET installer maps ".aspx" to the aspnet_isapi.dll- that's why the .aspx extension works. To map requests with no extension to the APS.NET engine, you must tell IIS to look at every request.
Here's a quick article that explains the process:
http://haacked.com/archive/2008/11/26/asp.net-mvc-on-iis-6-walkthrough.aspx
Hope that helps and reduces the "lame" factor of your URLs. :)
-Todd
Found the freakish and bizzare (and stupid) answer :)
If you don't add ".aspx" to the end of your route, nothing fires in the Global.asax, meaning you don't get any BeginRequest, AuthenticateRequest, EndRequest, etc... Also, you don't get SessionState or anything.
So, the "fix" was for me to just change my route from this:
RouteTable.Routes.Add("Blah", new Route("Blah/{reportName}", new MyHandler());
to this:
RouteTable.Routes.Add("Blah", new Route("Blah/{reportName}.aspx", new MyHandler());
How completely lame :) ... but it's a fix none-the-less!
When you say
"If you don't add ".aspx" to the end of your route, nothing fires in the Global.asax, meaning you don't get any BeginRequest, AuthenticateRequest, EndRequest, etc... Also, you don't get SessionState or anything."
Will IIS log such requests in the log files or they are just anonymous? what about Application variables and ViewState?
sorry i haven't tested it yet, but just asking if you might already know?
i have checked application variable and Viewstate, these two are obviously working.. not sure about server logs :S

Resources