right now i work on an already existing ASP.NET MVC Project, which has the problem that the session sometimes suddenly ends and the user gets redirected to the login page. Today i noticed something, the login page is always loaded in the background:
I don't have much Experience with ASP.NET MVC so i wanted to ask, what could be the reason this always gets loaded. The code is not documented so i could not find a reason for it. I use IIS 8 for deploying.
Update:
I have now tracked with Fiddler and i saw something, at first i thought that the session cookies gets dropped or replaced turns out it doesnt. Its there even on the login page.
Update 2:
I have now validated that the cookie is still in place and the login info is still stored after this forced logout. Is there a common issue in ASP NET which can cause that a session is still saved but not recognized anymore? Turns out it could be this ActionFilter:
namespace backend.Models.ActionFilter
{
public class HasUserId : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
if (filterContext.HttpContext.Session.GetInt32("UserId") == null)
{
System.Diagnostics.Debug.WriteLine("Session is not there anymore");
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { action = "Login", controller = "Account" }));
}
}
}
}
Update 3:
I think I have found the problem, the session state gets stored 'In-process' i have now changed it to 'State Service'. I hope this will solve my problem. Is it normal that the login still works even when the 'ASP NET State Service' is halted? This is my config:
<system.web>
<sessionState
mode="StateServer"
stateConnectionString="tcpip=127.0.0.1:42424"
stateNetworkTimeout="20"
timeout="240">
</sessionState>
</system.web>
This problem occurs if the login page is as the start page. You can change this by modifying the filter file and specifically in routes.MapRoute.
For more information you can view here
If you want to change redirection via IIS, you can not do that.
The answer for my problem was to change the handling of the session state from 'In-process' to 'Out-of-process'.
Related
We are experiencing some issues with returning variables stored in session, which in turn is causing our controller authorization code to redirect some users back to the login page. The users only seem to be having this issue with the Firefox browser and the application works normally for them when using Chrome or Edge. It's almost as if their session is being dropped while navigating through the site (mostly immediately after login while being redirected to the home page, however sometimes the user can get through few links before being kicked out).The issue also only happens after if is running in our test or production sites, reproducing the issue locally troublesome. I was wondering if anyone else has experience this type of issue before and if they were able to find a work around or resolve it. Our sessionstate is set to InProc.
Based on other threads I have read on here I have tried the following so far:
Ensured that Session_Start is in Global.asax, Tried setting a "dummy" session variable in the Session_Start method "Session["Init"] = 1", added this to our web.config file under the section
, as well as some other solutions I have found that turned out not to resolve our issue.
This is the section of code in question.
public class AuthorizeSessionAttribute : AuthorizeAttribute, IAuthorizationFilter
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
HttpSessionStateBase session = filterContext.HttpContext.Session;
Controller controller = filterContext.Controller as Controller;
if (controller != null && session != null && session["CurrentRole"] == null)
{
controller.HttpContext.Response.Redirect("~/Account/Login");
}
base.OnAuthorization(filterContext);
}
}
I just can't see any obvious reason as to why this would only happen in Firefox but work correctly in Chrome or IE. Any input on this would be appreciated. Thanks.
Im using Webforms throught C#
When the users does a certain action it might be redirected to another link, which is not working atm (it was before and i cant rollback the project since idh tfs or github)
The user is on this site:
localhost:53145/VistaUsuario.aspx
When it users fills the form and click accept the code behind is:
Session["user"] = txtDominio.Text;
Response.Clear();
Response.Redirect("FormOrden.aspx");
When it does the action it's redirected to the same link adding this parameters :
localhost:53145/VistaUsuario.aspx?ReturnUrl=%2fFormOrden.aspx
This is the code behind "FormOrden.aspx"
protected void Page_Load(object sender, EventArgs e)
{
string usuario = (string)Session["user"];
if (usuario != null)
{
this.MostrarDatos();
}
else
{
this.DoSomethingElse();
}
}
How to fix this?
It looks like you have Authentication enabled in your web.config. Your session is not authenticated so any attempt to go to another page goes back to the authentication page, which happens to be your current page (likely default.aspx).
The reason you see ReturnUrl="%2fFormOrden.aspx is because that's how Forms Authentication handles redirects after logging in.
Basically, you try to hit a page that requires authentication and are not authenticated. Forms Authentication redirects the request to the login page. Upon Logging in you make a call to FormsAuthentication to RedirectFromLogin page and it goes to the page specified in the ReturnUrl to go back to where the user was trying to go.
Either finish your authentication workflow, or turn off forms authentication in your web.config.
In my global I have the following code to handle when an error occurs
//[..] code goes here
Server.Transfer("~/Error.aspx?ErrorID=" + errorId);
It used to be a Response.Redirect which worked perfectly except that it changed the url (which is why I want to use Server.Transfer)
Unfortunately, now when it tries to load the Error page, it crashes on the Masterpage when it tries to refer to the Session
HttpException:
Session state can only be used when enableSessionState is set to true,
either in a configuration file or in the Page directive. Please also
make sure that System.Web.SessionStateModule or a custom session state
module is included in the \\
section in the application configuration.
I do have enableSessionState in both my config and my page.
I also found some links which suggest using Context.RewritePath - that just causes a blank page to load for me.
Using Response.Redirect works perfectly and as expected, so I assume Server.Transfer is the issue here. What is it?
EDIT Code:
protected void Application_Error(object sender, EventArgs e)
{
lock (_lockMe)
{
Exception ex = Server.GetLastError();
if (ex != null)
{
if (ex.InnerException != null)
ex = ex.InnerException;
ErrorLoggingManager.AddError(ex, new MembershipData(), ...); //etc
}
Server.ClearError();
//Some other database code for cleaning up some stuff when an error happens
}
try
{
if (Response != null)
{
//Get the last error logged
MyDataContext db = new MyDataContext();
int errorId = db.LoggedErrors.OrderByDescending(le => le.ErrorId).Select(le => le.ErrorId).FirstOrDefault();
Server.Transfer("~/Error.aspx?ErrorID=" + errorId);
}
}
catch (Exception)
{
}
}
As you have not posted much code. So without seeing the actual implementation you have done. I could suggest you below points.
Point 1. First of all, you need to check if SessionState is enabled for pages. You could set them globally in web.config file. Try the snippet given below in web.config
<configuration>
<system.web>
<pages enableSessionState="true" />
</system.web>
</configuration>
Point 2. And put your Redirection in Application_Error in Global.asax.
public void Application_Error(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)sender;
app.Server.Transfer("~/Error.aspx?ErrorID=" + errorId,true);
}
Point 3. Also check if your SessionStateis set properly in IIS too.
Details are on MSDN to enable sessionstate
Hope this helps..!!!
From what I understand, Server.Transfer sends the content of another page to the client rather than the requested content. If that is the case, then I am wondering if it does not have something to do with applying a master page to the error page? I had a similar error years ago with earlier technology and it turned out that the master page did not like what I was trying to do.
I hope this helps at least point to a solution.
Here's what the problem is:
If there is a page render exception (ex. "File Not Found") then Server.Transfer screws up the session. This has something to do with it being called during the page render.
As long as you are not appending headers before the error occurs, Response.Redirect will work just fine; if you are, however, using Response.AppendHeader then Response.Redirect will not work during a page render.
Try using HttpContext.Current.RewritePath instead. That should fix all these problems. For whatever reason, RewritePath() does not care that the page hasn't finished rendering.
why not just use customErrors in web.config to do the redirect?
<customErrors mode="Off" defaultRedirect="~/Common/Error.aspx">
<error statusCode="403" redirect="~/SM_AccessDenied.aspx" />
<error statusCode="404" redirect="~/Common/FileNotFound.aspx" />
</customErrors>
I had the same problem in a different context a while ago. I don't know if it is your case, but if you're using IIS7 on Windows 2008, in addition to setting enableSessionState=true in your web.config, you have to put your modules inside the <system.webServer> section, instead of <system.web>. Changing this little thing solved it for me.
Why don't you try like this:
The Server.Transfer method also has a second parameter—"preserveForm". If you set this to True, using a statement such as Server.Transfer("WebForm2.aspx", True), the existing query string and any form variables will still be available to the page you are transferring to.
So I think doing like this your session will not expire.
Server.Transfer("~/Error.aspx?ErrorID=" + errorId,True);
The error you are encountering is because you are using a query string parameter. Per the msdn docs
However, the path parameter must not contain a query string, or ASP returns an error.
http://msdn.microsoft.com/en-us/library/ms525800%28v=vs.90%29.aspx
Its about 3/4 of the way down the page just above Requirements.
Even though the docs here are mentioning asp. and not asp.net, keep in mind the session state is a feature of IIS and is handled before asp.net is ever called.
#user2110845 : I had faced similar problem few months ago. the problem was with having an underscore in the website name. We were deploying a website in IIS with two different host names(adding two entries through the 'Edit Bindings' option on the website). The host names provided were abc_ts, abc_is. When the underscore was removed then the session problem got resolved.
It seems there are certain characters not allowed in a website host name. Check if that is your problem.
I found the answer here : link (check 'update 2' in the article)
You don't mention what version of ASP.NET you are using, but there were some changes between 2.0 and 3.5 in how unhandled exceptions bubbled their way up through an ASP.NET web app and then IIS.
Among some other possibles, while you are clearing the error you are not setting Context.Response.TrySkipIisCustomErrors = true; While this particular flag could have nothing to do with your issue (and is only available for 3.5+), it also could help deal with what is potentially two error pages behind the scenes that are obscuring the real issue. Regardless, it'll save you a lot of grief (at least if you are running 3.5+) with other potential issues. Check out two posts I wrote several years back that may be helpful: while they don't cover session handling, they do cover the multiple song-and-dance routines I had to follow to get proper 500 and 404 handling in various versions of ASP.NET. It's possible you will run into something that will get you further ahead, if not all the way there.
http://www.andornot.com/blog/post/Errors-Sending-the-Right-Message-(Redux-Covering-ASPNET-3540).aspx
http://www.andornot.com/blog/post/Errors-Sending-the-Right-Message.aspx
Please bear with me as I am pretty new to designing websites.
When someone goes to my website they are initially sent to a log in page, which is defined in my web.config as:
<authentication mode="Forms">
<forms loginUrl="~/Login/Index" timeout="15"/>
</authentication>
However, before they log in I check whether the database they want to access has been defined (this is something that users may want to change frequently), and if it has not I want to send them to a different form. So, my login controller index looks like:
public ActionResult Index()
{
bool settingsSetUp = SupportLibrary.Settings.CompanyId != null;
if (settingsSetUp)
return View();
else
return RedirectToAction("index", "setup");
}
However, when I try this I always get "This page has a redirect loop" in Chrome. The page will not display in Firefox of IE either. On investigation the above method is always being called numerous times, so that eventually the browser decides it is being redirected too often. If I just set it to go to the view associated with the controller (no redirection) it calls the above method 15 times. Otherwise it is called 10 times before Chrome displays the error message.
Does anyone know why it is being called so many times as I think that is the root of the problem? Many thanks!
You are trying to load actions that require the user to be authenticated (they either have the Authorize attribute on them or it has been applied globally) which is causing a redirect back to the login action.
Check your actions to ensure that they can be accessed without being logged in if required.
I'm trying to setup Forms Authentication in an asp.net mvc 2 application that will be hosted on IIS 6. There's an issue somewhere in my routing, but I can't pinpoint exactly where it is.
Here is the route entries I'm using to route the mvc requests through the aspx processing on IIS 6. These may or may not be the "right" way, but they do work on the server at current.
routes.MapRoute(
"Default",
"{controller}.aspx/{action}/{id}",
new { action = "LogOn", id = "" }
);
routes.MapRoute(
"Root",
"",
new { controller = "Main", action = "LogOn", id = "" }
);
I've put the [Authorize] attribute on my Main controller.
In my web.config I have:
<authentication mode="Forms">
<forms loginUrl="~/Main.aspx/LogOn" timeout="2880"/>
</authentication>
When the application starts, a blank page loads. The page is quite literally blank. I haven't found a way to amend the loginUrl to actually execute the LogOn action & View for my Main controller.
Edited
Just as an fyi, I've setup my routing based on this article so that the mvc routing can work on IIS 6.
http://www.asp.net/mvc/tutorials/using-asp-net-mvc-with-different-versions-of-iis-cs
I'm guessing the problem here is that the windows form authentication settings aren't syncing with the routes setup so the app can run on IIS 6 via the aspx extension.
Anyone have thoughts on how I could fix this?
Edit 2
Tried adding the following route:
routes.MapRoute(
"Login",
"Login",
new { controller = "Main", action = "LogOn" }
);
Amended the web.config to:
<authentication mode="Forms">
<forms loginUrl="~/Login" timeout="2880"/>
</authentication>
The result is the same white screen as I originally got. It seems like the page doesn't get processed at all. Viewing the source from page generated shows absolutely nothing....no markup...no html declaration....just nothing.
EDIT 3
It seems that I can't seem to get the correct routing configured with the default forms authentication via the web.config. To circumvent this, I've created my own Authorize attribute class. At current, I only care that the user has logged into the system. To accomodate this, I moved the LogOn & LogOff actions to an Account controller. I've remapped the root path to point to this controller. In my custom Authorize attribute, I check to see if the user is logged in and redirect them back to the LogOn page if they aren't. Here is the code:
routes.MapRoute(
"Root",
"",
new { controller = "Account", action = "LogOn", id = "" }
);
And here's the code for the RequireLoginAttribute class I derrived.
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class RequireLoginAttribute : AuthorizeAttribute, IAuthorizationFilter
{
#region IAuthorizationFilter Members
public override void OnAuthorization(AuthorizationContext filterContext)
{
if (!filterContext.HttpContext.Request.IsAuthenticated)
{
//This didn't work...it would try routing to urls like
//http://localhost:1524/Main.aspx/Account.aspx/Logon
//new RedirectResult("Account.aspx/Logon");
//This seems sloppy to me somehow, but it works.
filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary(new { controller = "Account", action = "LogOn" }));
}
}
#endregion
}
Now, I can just apply the [RequireLogin] attribute to the Main controller and it ensures the user must be authenticated.
For the curious, and completeness of this scenerio, I am using the following code in the LogOn action (repository isn't ready yet so things are hard coded):
public ActionResult LogOn(LogOnModel login, String returnUrl)
{
if (ModelState.IsValid)
{
FormsAuthentication.SetAuthCookie(login.UserName, false);
return Redirect(returnUrl ?? Url.Action("NextPage", "Main"));
}
else
{
return View(login);
}
}
The returnUrl is a throwback to the Windows Forms authentication. Since I can't seem to get that working here, the parameter will always be null.
Please, critique this if you see specific areas that need improvement. I'm reading what I can and trying to do things right, so all input is greatly appreciated. Thanks!
If you need the .aspx for the Default Root then why don't you need it for the login route ?
You could do a couple of things then
Actually create a ASP.NET page called Login.aspx and put it in the root of the folder (Authentication will work for your mvc pages as well)
Change your login route to say
routes.MapRoute("Login","Login.aspx",new { controller = "Main", action = "LogOn" });
You should also take a look at to see what route your actually hitting at any time.
http://haacked.com/archive/2008/03/13/url-routing-debugger.aspx
Remember that the order you write your routes in Global matters. It stops checking when it finds one that works so your catch all should be last.
The details I posted in EDIT 3 summarize the solution to this issue. I appreciate all of your input into this question, but I've resolved it. I would have liked to have gotten the "out of the box" forms authentication working, but this solution serves well enough. If we move to IIS 7, I think all of this will become moot anyhow.
Thanks again for your help guys.