Session is reseting on RedirectToAction across controller - c#

I have one loginController With Index Mathod as
public ActionResult Index(string something)
{
Session.Abandon();
Session["ActiveUser"] = _user;
return RedirectToAction("All", "User");
}
and UserContoller as
public ActionResult All()
{
var _currentUser = ((AuthUser)Session["ActiveUser"]);
}
the problem is when redirect Happens the session state resets, I am not able to understand why ?
any help or resource will be appreciated.

Edit
I had also written Session.Abandon(); in the start when I removed that from I code it started working fine.
Yeah, that would explain it. Calling Session.Abandon queues the Session for destruction/removal and executes it when your initial request (before the redirect starts) finishes processing. So anything you do to Session (including TempData) in that initial request is essentially ignored because the entire session including changes is discarded. From the documentation.
When the Abandon method is called, the current Session object is queued for deletion but is not actually deleted until all of the script commands on the current page have been processed. This means that you can access variables stored in the Session object on the same page as the call to the Abandon method but not in any subsequent Web pages.
there is no special configuration of Session in the webconfig #Igor
Then the Session state is not enabled which is why you can't retrieve anything from Session or TempData. You need to configure the session state in the web.config. If you are only using this for TempData you can configure it for InProc. If you want to configure long term storage (data available across multiple requests) and you have multiple servers (ie. web farm) that can handle requests you should look at configuration using a store like Sql Server.
You can make the configuration changes either directly in the web.config (see SessionState documentation)
<sessionState mode="Off|InProc|StateServer|SQLServer"
cookieless="true|false"
timeout="number of minutes"
stateConnectionString="tcpip=server:port"
sqlConnectionString="sql connection string"
stateNetworkTimeout="number of seconds"/>
Or using IIS (see screenshot below).

Related

Threading issue in ASP.NET Core

I have an ASP.NET Core Web API project. That has one controller with a method called GetLocations
GetLocations connects to 5 other web services on the internet. Gathers some info and return a collection via json. In this method I am caching the data every 5 mins using In Memory caching.
If the cache expires, it tries to connect to all 5 services and get the info and so on.
My problem is:
I have a lot of users requesting this data constantly, 50 requests a second to this API.
When the cache expires I believe there is some kind of thread locking. I have limited visibility into the project at the moment but I suspect that all these requests are calling the method and reaching out to the 5 dependent services until one of them gets a completed response from all 5.
Is my assumption right? If so how can I go about fixing this? Will I need to make each call to the web services async? Will that help this scenario? I am not 100% sure because the requests are what triggers the method call.
You should definitely make the calls to the external services use Async / Await.
That's just a given - as the best practice is to always use async for I/O heavy operations (such as calling a third-party service).
Now, you should also create a class that manages these calls. You can add it as a Singleton in your IoCConfig. In that class, make sure you're "locking" to avoid the issue you just described and not call the underlying services numerous times while the cache is being built.
Check here:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/lock-statement
You are facing this issue because of following reason.
You are using Cache and it will expire at some definite time.
After Cache expire you call external web service method to collect the data. Now at this point of time it might happen that other request in queue get choose for execution.
Once that another request is chosen for execution it also end up checking cache and it now data in cache then execute external service and so on for other request.
Solution to this.
First Check cache contains data or not.
If Not create lock so following section only be executed by single thread.
Now in that lock section again check for cache and if cache contains data then simply return but it does not contains then call external service.
At this point of time if another thread get selected for execution then it has to wait for execlsive section to complete its works.
Once that section get completed it store data in cache and so after if any queued or new request is there it choose data from cache.
Note : It should something like this.
public List<string> GetData()
{
if(Cache[key] == null)
{
lock(obj) // obj should be static
{
if(Cache[key] == null)
{
// Load data from service
Cache[key] == data;
}
}
}
return (List<string>)Cache[Key];
}

Does SessionID change for each call to webservice?

I don't understand the notion of session for webservices. In one hand you can allow session in DataAnnotation like that :
[WebMethod(EnableSession = true)]
In the other and you can configure the session state in IIS :
So I put Session State in process and set the delay for 20 minutes.
Then in my webservice I try to get the session ID like that :
return HttpContext.Current.Session.SessionID
I use a winform to get this information and call the webservice.
And the session ID Change at every call. I don't understand why, beaucoup SessionState is set to 20 minutes...
May I'm in wrong way ? Can you explain me ?
Is SessionID correspond to the Session State in IIS ?
There must be something that connects the request to a particular session. Usually a cookie is used for that. This cookie is sent along with the response, so the calling application must remember that cookie and send it along with the next request. Without cookie the request is handled as if it's a new session.
A browser handles this by default (unless specifically switched off), for an other application you need to do cookie management yourself. For this you need to use a single CookieContainer that will be shared among your requests.
See the link in the answer by Marius for more details.
I was thinking of a solution, but then I found this post :
How to keep session alive between two calls to a web service in a c# application?
I hope this helps.
If you want to keep your sessionID same througout users session life time you should add a global.asax file to your web project and implement Session_Start method.
Please check this link:
https://msdn.microsoft.com/en-us/library/system.web.sessionstate.httpsessionstate.sessionid.aspx

WebAPI Cookies with ReportViewerWebControl

I have an MVC application that also includes an ASP.Net WebForm to host the MS ReportViewer Web Control. We make extensive use of WebAPI to allow for client posting from Knockout viewmodels client side.
In this application, we're making use of cookies to maintain a few minor pieces of user data--a GUID, an int, and a bool.
What we see at present is that the application works correctly until a user opens the ReportViewer. At that point, we're no longer able to read any cookies from the request headers. This has been consistently reproduced in several browsers.
Examination with Fiddler has revealed that the cookies are properly posted to the server. In the first case, the cookie value is as follows:
theCulture=en-US; ASP.NET_SessionId=uhmquapd1bgghpmfgy24oodf; .ASPXAUTH=6BC2F53F9CA0CF5A437998B206B564B28B5AB362153E6E0629C9142F9E3A0285494F674716A126E4632A932BCE12CE094FE590911CE5E97EA42D0C610A44D8462A15BA9A54760883DDF712B5B199C136413667954F094FEBA2A57826BC84702A4D90D7382E360594ABC2F9EBDCEE696B4662077F; special=theId=1077b59a-100d-429b-b223-f8f0508fdc27&staffingId=77096&isBackupUser=False
In the second case, after opening the ReportViewer, our cookies are as follows:
theCulture=en-US; ASP.NET_SessionId=uhmquapd1bgghpmfgy24oodf; .ASPXAUTH=6BC2F53F9CA0CF5A437998B206B564B28B5AB362153E6E0629C9142F9E3A0285494F674716A126E4632A932BCE12CE094FE590911CE5E97EA42D0C610A44D8462A15BA9A54760883DDF712B5B199C136413667954F094FEBA2A57826BC84702A4D90D7382E360594ABC2F9EBDCEE696B4662077F; special=theId=1077b59a-100d-429b-b223-f8f0508fdc27&staffingId=77096&isBackupUser=False; /Reserved.ReportViewerWebControl.axd%3FOpType%3DSessionKeepAlive%26ControlID%3Dc3b959ab1a7c42e6a9fed5d2762a8c86_SKA=1
At which point we can no longer read them from WebApi. The method that returns the cookie in the WebAPI Controller is this:
public OurType GetApproverInfo()
{
OurType data = new OurType();
CookieHeaderValue cookie = Request.Headers.GetCookies("special").FirstOrDefault();
CookieState cookieState = cookie["special"];
data.Id = Guid.Parse(cookieState["theId"]);
data.StaffingId = Int32.Parse(cookieState["staffingId"]);
data.IsBackupUser = bool.Parse(cookieState["isBackupUser"]);
return data;
}
Anyone else seen something like this?
UPDATE: I've just learned that creating a cookie with a leading / in the name causes the same behavior in WebAPI.
What I see is that the ReportView is messing up the cookie. Probably you're setting up the cookie somewhere in the WebApi that has not the same pipeline execution sequence as the ReportView Handle.
Heres the WebApi life cycle: ASP.NET WEB API: HTTP MESSAGE LIFECYLE
But, you can override the ReportViewerServerConnection, using IReportServerConnection, and there persist yours cookie pattern.
Take a look here: Web.config Settings for ReportViewer
Another way should be setting up the cookie in a Custom IHttpModule, integrated into the ASP.NET pipe line, and then target both, WebApi and ReportView

Session ends randomly after redirect

I have a strange problem in ASP .NET MVC 4. In AccountController I am doing redirects on certain actions and put data into TempData (which is stored in Session) before that:
[AllowAnonymous]
public ActionResult Activate(string token)
{
new CustomSignupService().Activate(token);
TempData["Message"] = "User was successfully confirmed";
return RedirectToAction("Message", "Home")
}
Now I know I could just return shared Message view in this case, but this is just a code sample to reproduce the problem.
CustomSignupService.Activate does a db lookup via NHibernate and updates user in transaction (user activation). Sometimes (lets say 1/5 tries in 5 minutes) TempData does not make it throught the redirect, so I added logging into Session_End and noticed that session ends when RedirectToAction is invoked. Right after that Session_Start is invoked but of course TempData is gone.
Session has default timeout (20min) and controllers use SessionStateBehavior.ReadOnly
Any ideas?
UPDATE
Step 1: It's not Application Pool recycling (I turned on all General Recycle Event Log entries on Application pool and checked event log, after session restarts but recycle is not causing it)
I had a problem with Session being lost. I used Fiddler and noticed that there was a duplicate ASP.NET session cookie with a blank value. I don't know how it got there. So a new session was created on every request. I deleted that duplicate cookie and the problem was solved.
Other unlikely reasons are:
IIS process recycle
Session.abandon being called
modifying bin folder or web.config causing app restart
Check out this page:
Losing Session State
I don't know ASP.NET MVC but in the dark centuries I used ASP.NET without MVC. I struggled several times with unexpected session ends. Most of the time it was caused by some simple things which are described in the article http://www.c-sharpcorner.com/uploadfile/technoNet/session-timeouts-causes-and-remedies/
Sometimes the server has entries in the event log that gives you a little bit more information.
And some other solutions might be
ASP.NET Session ending abruptly
random IIS session timeout

Session Id Changing Randomly

I have a simple ASP.NET MVC application. When the first action method is run it stores some data in the Session variable. On the resulting view I have a jquery ajax call triggered by a button to another action method.
When I click the button a different session id is used at the server side, it's a bit random. There is sometimes a gap of a second or so between starting and clicking the button and the Session ID still changes. This breaks the app as it tries to retrieve the data stored by the first action method.
Any idea what's going on? Both requests are to the same URL.
I see method one instantiate a new session with Id X and store the data.
Immediately after loading the Jquery request fires. I see a different session cookie id on the request header.
I get an error "data not found"
Many thanks,
This is by design and ASP.NET tries to be efficient in storing sessions for users. Remember unless you store anything in session the session value changes.
If you want to tell ASP.NET that you want it to track user sessions, you can do one of 2 things:
Store something in the session.
Simple handle the Session_Start event in your GLobal.asax. The presence of this method will tell ASP.NET to track sessions , even if there is no data in the session..
// NOTE: There is no need to add any thing to session if you are doing this...
public void Session_Start(object sender, EventArgs e)
{
}
This behavior had caused me much worry in the past :)
Are all your AJAX calls using the same server name:
http://localhost/whatever
vs
http://machinename/whatever

Categories