When is Session_End() called in ASP.NET MVC? - asp.net-mvc

I have configured my Web.Config file as follow in a ASP.NET MVC 2 project:
<sessionState mode="InProc" timeout="1"/>
And added the following in Global.asax.cs:
protected void Session_End(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("Session_End");
}
protected void Session_Start(object sender, EventArgs e)
{
System.Diagnostics.Debug.WriteLine("Session_Start");
}
Session_Start() is called when a new user goes on the website. I would have expected Session_End() to be called after 1 minute of idle time, but it's not the case. Am I missing something?

Remember this:
If you don't save anything into the session, the session_end will not
fire. If you're saving data in the session in the first request, and calling abandon in the
same request the session_end will also not fired.
Hope this helps!
T
btw:
ASP.NET Session_End event not firing

Be patient. The event should be called, but not necessarily right after the timeout.
You could try from a Browser: Start a session,wait > 1 minute, do a Postback somehow
This should help to verify that the Timeout works and I think you will also see the SessionEnd happening at that time. Otherwise, just wait and start some other sessions. The system will come around o calling it sometime.

Tip for testing: Use Session.Abandon so you don't have to mess with your actual web.config value. Just don't set a session value and call Session.Abandon during the same request or it won't get stored.

Related

FluentNhibernate configuration exception handling in application_start

I am initializing FluentNHibernate from Application_Start event like so:
Fluently.Configure()
.Database(OracleDataClientConfiguration.Oracle10
.Driver<NHibernate.Driver.OracleDataClientDriver>()
.ConnectionString("MyConnectionString")
.DefaultSchema("MySchema")
)
.Mappings(m => m.FluentMappings.AddFromAssemblyOf<SomeClass>())
.BuildConfiguration()
.BuildSessionFactory();
If the connection string is bad, or connection to the DB fails for some other reason, I get a TNS No listener exception. I would like to display/log this exception but Application_Start (and Applicaiton_Error) doesn't have an HttpContext or Response object in IIS7 Integrated mode. The user gets a yellow screen of death telling them to turn custom errors On. Elmah doesn't log the message either. I would like to solve the problem in one of two possible ways:
Disable nhibernate configuration from connecting to the database on configuration.
Provide custom user feedback based on the error and get Elmah working (somehow). This would be my ideal choice.
I was able to move NHibernate configuration to run on Session_Start, as described here, which gets exception handling working for this error, but then I get other exceptions that can be misleading to the root cause of the problem. Does anyone have a good solution for this scenario?
Thank you.
This is what I do:
void Application_Start() {
try {
// setup your app / nhibernate
} catch(Exception ex) {
Application["StartupError"] = ex
}
}
void Application_BeginRequest() {
var startupError = Application["StartupError"] as Exception;
if (startupError != null)
throw new Exception("Error starting application", startupError);
}
In your BeginRequest method you have access to the Request and can do what you want to show the error (or show a nice page)

Handling a timeout in ASP.NET MVC

In ASP.NET MVC3, I can't seem to override a session timeout. I have set breakpoints at all the relevant server-side code points I can think of (controller actions and methods in globax.ax.cs) but nothing seems to get hit on session timeout.
I even applied an attribute as suggested here: (http://www.tyronedavisjr.com/2008/11/23/detecting-session-timeouts-using-a-aspnet-mvc-action-filter/) but even it was not hit when the session timed out. Surely the timeout must be session-side, but where?
Does anyone know what exactly happens when an ASP.NET MVC application has a session timeout?
What sessionState mode are you using? (<sessionState mode=" ... "> in web.config)
You should be able to add the following method to your Global.asax.cs to override the default Session_End behaviour:
protected void Session_OnEnd(object sender, EventArgs e)
{
// insert code here
}
Things to bear in mind:
The Session_OnEnd / Session_End event will only be called if the HttpSessionState.Mode property value is InProc (this is the default, so if you've not changed it in the web.config this should be fine). If you've changed it to StateServer or SQLServer, then the Session_OnEnd event in the Global.asax file is ignored.
The Session_OnEnd / Session_End event is called by the application when it abandons the session - not when you close the browser. You can manually trigger it by calling Session.Abandon
Typically, session timeouts can be handled in the Session_End event in your Global.asax
void Session_End(object sender, EventArgs e) {
// perform last minute procedures before session ends
}
According to the MSDN, the HttpSessionState.Timeout property has a setter and can be changed from within your application's code as well as permanently in the web.config

ASP NET MVC Making request strange behaviour

First of all, sorry for my bad english.
I have faced a strange problem using asp net mvc.
I have simple controller, which can execute 2 operations. The first operation is continuous and can take a several minutes. And the other is short, and executed some seconds.
Something like this:
public class TestController : Controler {
[HttpPost]
public string Func1(long id) {
// continuous operation
return new ValueGetter().Get(id)
}
[HttpPost]
public string Func2(long id) {
return "Abc";
}
}
And from the client side i call thouse methods via jqueries post:
$.post(url).sucess(...);
The problem consists in the next: while the first operation is executed, the second operation will wait, until first is finished.
I tried to use AsyncController as described there http://msdn.microsoft.com/en-us/library/ee728598.aspx, but the result is the same...
I have logged some application events in global.asax:
protected void Application_PostMapRequestHandler(object sender, EventArgs e) {
LoggerManager.Info("PostMapRequestHandler fired in global.asax");
}
protected void Application_AcquireRequestState(object sender, EventArgs e) {
LoggerManager.Info("AcquireRequestState fired in global.asax");
}
And if I for example, call the first method once, and then Immediately call the second method three times, I have the following result in the log file:
1.PostMapRequestHandler
2.AcquireRequestState
3.PostMapRequestHandler
4.PostMapRequestHandler
5.PostMapRequestHandler
... after first method is executed sucessfuly
6.AcquireRequestState
7.AcquireRequestState
8.AcquireRequestState
I use IIS 7(not express) and asp.net mvc 3
Why it happen and how I can solve it?
I found the answer to my question here:
Session less MVC Controller for MVC 2 / RC (MSDN Blogs)
I hope it will help, if someone faces a similar problem.

Page Redirect when session end in ASP.Net MVC

I would like to do redirect to login when current session end and that config must be working at any View and Controller.
My current code in Global.asax:
protected void Session_End(object sender, EventArgs e)
{
Session.Abandon();
//GetPath() is getting currently path
// eg. http://localhost/mymvcproject
Response.Redirect(PATH.GetPath() + "User/LogOn");
}
Check the following setting under <system.web> in your web.config file:
<sessionState mode="InProc" cookieless="false" timeout="1"></sessionState>
then fill the following text in your site.Master
if (Session.IsNewSession)
{
Response.Redirect(PATH.GetPath() + "User/LogOn");
}
I don't think your code can work because Session_End() is more usually invoked when there is NO request made by the browser after a specific duration. Therefore, Response here would correspond to no particular request, and thus, no redirection.
Instead, try to handle Application_Start and check for Session.IsNew property. If it's true, then perform the redirection. (Consider doing that by invoking FormsAuthentication.RedirectToLoginPage() though.)
When checking for IsNew, beware of the situation described here. I guess assigning some dummy session variable during the login process will address that, although I haven't tried myself.

Understanding the ASP.NET MVC execution pipeline to generate a page creation time

Where do i start the stopwatch and where should it stop?
The logical place for the stopwatch to start should be the controller action method, yes, no?
But where should the stop the clock? I would like to think that it goes at the end of the master page? It doesnt make sense to stop the watch at the end of the controller action method because there will additional process which happens in the View to render the page.
Any thoughts?
EDIT: I intend to use the elapsed time within a master page so i can get the time for any webpage.
Darin: Thanks for the code sample. But the sample does not work as i expected. I planned to use the elaspsed time in a master page so it can be written to every page.
So i think the Master page would've already loaded by the time EndRequest get executed?
In my EndRequest i set:
Context.Items["PageCreationTime"] = watch.ElapsedMilliseconds.ToString();
Then i my masterpage iam unable to get reference:
<%= HttpContext.Current.Items["PageCreationTime"].ToString()%>
Application.BeginRequest and Application.EndRequest are good candidates.
protected void Application_BeginRequest(object sender, EventArgs e)
{
Stopwatch watch = Stopwatch.StartNew();
Context.Items["watch"] = watch;
}
protected void Application_EndRequest(object sender, EventArgs e)
{
Stopwatch watch = (Stopwatch)Context.Items["watch"];
watch.Stop();
// Do something with the results like for example:
Context.Response.Write(watch.ElapsedMilliseconds);
}
I thnk you'd best place it in the EndRequest event handler in the Global.asax. Something like:
protected void Application_EndRequest(object sender, EventArgs e)
{
Stopwatch.Stop();
}
The EndRequest event is fired at the very end of earch request. You could start your stopwatch in the beginrequest eventhandler:
protected void Application_BeginRequest(object sender, EventArgs e)
{
Stopwatch.Start();
}
Starting it in the controller action may be too late (depending on what you want to measure) since a lot of other code will have run at that point, even custom code you wrote yourself, e.g. when you place custom attributes on your controller action.

Resources