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
Related
I am using MVC 4 and have Actions that need to accept input that includes HTML tags. The Actions are only accessible by trusted administrators, so I allowed the HTML tags by adding the ValidateInput(false) attribute to the relevant Action methods.
This worked fine initially, but subsequently I have added code to Global.asax to prevent Forms authentication redirection for Ajax requests:
if (FormsAuthentication.IsEnabled && context.Request.IsAjaxRequest())
{
context.Response.SuppressFormsAuthenticationRedirect = true;
}
After adding this code, I started getting an HttpRequestValidationException on these Actions, thrown from IsAjaxRequest:
System.Web.HttpRequestValidationException (0x80004005): A potentially dangerous Request.Form value was detected from the client (...).
at System.Web.HttpRequest.ValidateString(String value, String collectionKey, RequestValidationSource requestCollection)
at System.Web.HttpRequest.ValidateHttpValueCollection(HttpValueCollection collection, RequestValidationSource requestCollection)
at System.Web.HttpRequest.get_Form()
at System.Web.HttpRequest.get_Item(String key)
at System.Web.Mvc.AjaxRequestExtensions.IsAjaxRequest(HttpRequestBase request)
at MyApp.Application_BeginRequest(Object sender, EventArgs e)
...
What's the best way to fix this?
I'm wondering if SuppressFormsAuthenticationRedirect is breaking this option in web.config:
<pages validateRequest="false"
I had the exact same situation and putting [AllowHtml] on my password field fixed the issue.
Either one of two things is true:
1) SuppressFormsAuthenticationRedirect did disable the effect of validateRequest=false
2) It never worked in the first place.
Not sure which is true but now it works.
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)
I am using Asp.Net MVC and NHibernate.
Some of my Global.asax file is shown below:
public override void Init()
{
base.Init();
// The WebSessionStorage must be created during the Init() to tie in HttpApplication events
webSessionStorage = new WebSessionStorage(this);
}
/// <summary>
/// Due to issues on IIS7, the NHibernate initialization cannot reside in Init() but
/// must only be called once. Consequently, we invoke a thread-safe singleton class to
/// ensure it's only initialized once.
/// </summary>
protected void Application_BeginRequest(object sender, EventArgs e)
{
//the following code sets up the NHibernate Session Factory
NHibernateInitializer.Instance().InitializeNHibernateOnce(
() => InitializeNHibernateSession());
}
Whenever the AppPool recycles the next request is taking a while to execute due to it having to wait for the NHibernateSessionFactory to initialise. After that everything is fine until the next app pool recycle.
Now I'd like to move the initialization into the Application_Start method, so that when the pool recycles, the restart does the heavy lifting PRIOR to the next request coming in. However the comment "Due to issues on IIS7" which comes from S#arp architecture made me realise it's not that simple.
I did find an article: http://scottsdalewebstudio.com/blog/mvc/mvc-sharp-iis7-nhibernate/ which suggests that setting IIS to use "Classic Mode" fixes it - is this the only way?
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.
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.