How to handle Session on each request Asp.net mvc - asp.net

I have an web application running in mobile application(WebView).When user open the app, mobile app sends me the language info of the telephone through the request. Since the language value comes only on the first request and then deleted, I have to take it and store it for subsequent requests. I have tried PreRequestHandlerExecute and Application_AcquireRequestState on global.asax. I control the Session. if it is null I get the value from request, if it is not null I get it from session. But it seems like session is always null and always get the value from request. Any idea would be very helpful? Thanks for advance.
var dilKodu = Request.Headers.GetValues("languageCode");
CultureInfo ci;
if (dilKodu != null)
{
//I set culture from request if it is not null.
ci = new CultureInfo(dilKodu[0].ToString());
this.Session["Culture"] = ci;
}
else
{
if (HttpContext.Current.Session != null)
{
//I get culture from Session if its set before.
ci = (CultureInfo)this.Session["Culture"];
if (ci == null)
{
string langName = "tr";
//If culture exist neither Session nor Request
ci = new CultureInfo(langName);
this.Session["Culture"] = ci;
}
}
else
{
ci = new CultureInfo("tr");
}
}
Thread.CurrentThread.CurrentUICulture = ci;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);

Going by your code you are always going into the first if statement which will read and set the code form dilKodu
Your code should be more like this
if (HttpContext.Current.Session != null)
{
ci = (CultureInfo) this.Session["Culture"];
if (ci == null)
{
var langName = Request.Headers.GetValues("languageCode");
Session["dilG"] = langName;
ci = new CultureInfo(langName);
Session["Culture"] = ci;
}
}
else
{
Session["dilG"] = "session hazır değil tr yapıldı";
ci = new CultureInfo("tr");
}
Basically you have the if statements incorrectly setup for what you are trying to do.
Also it might be advisable to keep your session objects small, that is just store langName in the session and create a CultureInfo from that each time rather than store CultureInfo.

Is this an MVC web app? If so, you could try to save the value in the Controller.TempData property.
So instead of doing this.Session["culture"] = ci; you would add to the TempData property TempData.Add("culture", ci);. This would make the culture available for the next request. You would just need to make sure that you re-add the ci value in each request to make the value persist for as long as you need it.
Documentation for TempDataDictionary: https://learn.microsoft.com/en-us/dotnet/api/system.web.mvc.tempdatadictionary?view=aspnet-mvc-5.2

It was bcause of a setting in the web.config.
<httpCookies requireSSL="true" httpOnlyCookies="true"/>
I was trying to secure cookie but it prevent sessions. I delete it and now everything is works just fine. But I still need to find a way to secure cookies.

Related

Retain the session value when browser is opened for the second time

First time login to the asp.net application,stored some session value
Eg: Session["Test"]="Saving Sesison";
Logout the application
When opened the browser for the second time,need to retain the same session value.
Eg: Session["Test"]="Saving Sesison";
How can i do that,can anyone help me with some solution to proceed further please.
if (!Page.IsPostBack)
{
if (Session["Test"] == null)
{
Binding data to repeater control(with out filter)
}
else
{
//Get Session value (To maintain session value across the browser)
var cookieSession = Request.Cookies["Test"]; //While opening the browser for the 2nd time,this line is getting null for all the browsers,but session is getting value for firefox & Chrome not for IE { Session["Test"] }
if (cookieSession != null &&!String.IsNullOrEmpty(cookieSession.Value))
{
Session["Test"] = cookieSession.Value;
}
Binding data to repeater control(with filter using session value)
}
}
//On Drop down selection.
protected void Dropdown_SelectedIndexChanged(object sender, EventArgs e)
{
Binding data to repeater control(based on the dropdown selected value)
Session["Test"] = Dropdown.SelectedItem.Text.ToString(); //To maintain the Dropdown selection all over the app
// Set it
if (Session["Test"] == null)
{
Session["Test"] = Guid.NewGuid().ToString();
var cookie = new HttpCookie("Test", (string)Session["Test"]);
Response.Cookies.Add(cookie);
}
}
ASP.NET Session scope is for only particular session only. So its not possible to have that kind of functionality.
But you can use Cache in same way and it will be there until you make it null or time period exceeds. But beware of fact that it will be there for every browser. So either you need to use different key(Unique key) not like 'test'
You have a few options. Though sessions should be sticky between a browser being re-launched assuming it's not in private/incognito mode. If you're finding the session is timing out too quickly you can extend it in Web.config
<system.web>
<sessionState timeout="10080" mode="InProc" />
</system.web>
Where timeout is in minutes. Note: If you're are debugging stopping and starting the debugger will reset your sessions. So will any kind of re-deployment of the application on IIS. If this is an issue for you, you should check out using something like the SQL session state provider: http://msdn.microsoft.com/en-us/library/vstudio/h6bb9cz9(v=vs.100).aspx
Another method of dealing with this is to store some kind of token in a cookie (again, only works if the browser is not in incognito/private mode, and the user data hasn't been flushed).
// Set it
if (Session["Test"] == null)
{
Session["Test"] = Guid.NewGuid().ToString();
var cookie = new HttpCookie("Test", (string)Session["Test"]);
Response.Cookies.Add(cookie);
}
// Get it
var cookieSession = Request.Cookies["Test"];
if (cookieSession != null && !String.IsNullOrEmpty(cookieSession.Value))
{
Session["Test"] = cookieSession.Value;
}
As a note using the SQL session state provider while is one of the more persistent storages there can be some serious overhead requirements. It's easy to rack up a couple of gigs worth of sessions that are being tracked.
In my experience a combination of cookies and the session provider seem to work best if you need to be very certain that some things are sticking to a users experience on the site.
Edit
So the issue with your drop down selection saver is it's always false and should never set the cookie.
protected void Dropdown_SelectedIndexChanged(object sender, EventArgs e)
{
//Binding data to repeater control(based on the dropdown selected value)
// add to Session
Session["Test"] = Dropdown.SelectedItem.Text.ToString();
// Add Cookie
var cookie = new HttpCookie("Test", (string)Session["Test"]);
Response.Cookies.Add(cookie);
}
Now to get your data back out, put this code in the actions/controllers to run BEFORE you try to access Session["Test"]
var cookieSession = Request.Cookies["Test"];
if (cookieSession != null && !String.IsNullOrEmpty(cookieSession.Value))
{
Session["Test"] = cookieSession.Value; // Should contain the selected text from the drop down
}

New item added to session on every request

I found this behaviour by accident, as I return the count of items in a session in an error message and found that some sessions had as many as 120 items in them (they should have 1!). On further investigation I found that every request seems to add an item into the session. They are all negative integers, like -710, -140 -528. I can't seem to see a pattern in what number comes up.
I have checked my code for any interactions with the Session object and as far as I can tell it is not me. I store one item in the session which is my own object which has a number of other properties on it. My session state is SQL server, and I am only serialising a certain set of values that need to be kept.
Has anyone seen anything like this or has any advice on where I can troubleshoot further?
Thank you in advance.
-- Edit, as requested - first where I count the items in the session - this is done in the page load event of my master page. I loop through so I could inspect using the debugger.
int itemCount = Session.Count;
for (int i = 0; i < itemCount; i++)
{
object o = Session[i];
}
-- here is where I add my custom object to the session. This is called at session start and in my master page. It runs on a "get, but if not there, create" principle.
HttpSessionState Session = HttpContext.Current.Session;
HttpRequest Request = HttpContext.Current.Request;
if (Session == null)
return null;
SessionData sessionData = (SessionData)Session[StaticNames.SESSION_NAME];
if (sessionData == null)
{
sessionData = new SessionData();
Session.Add(StaticNames.SESSION_NAME, sessionData);
}
I also have this to get the SessionData object from the session:
public SessionData(SerializationInfo info, StreamingContext ctxt)
{
this.IsManualLogin = (bool)info.GetValue("IsManualLogin", typeof(bool));
this.HasAskedUserForLocation = (bool)info.GetValue("HasAskedUserForLocation", typeof(bool));
// ... etc, more items for all users here
int? loginID = null;
try
{
loginID = info.GetInt32("LoginID");
}
catch
{
return;
}
this.LoginID = loginID.Value;
// ... etc, more items for logged in users only
}
There is also an equivalent method for adding this data to the SerializationInfo used for SqlSessionState.
Credit to the modest jadarnel27.
It turns out the Ajax Control Toolkit NoBot control adds an integer into your session on every request. My website has an auto 40 second refresh, similar to facebook, so this probably would have brought the whole thing crashing down at some point and I am lucky to find it now. Should anyone else consider using the NoBot control, be warned about this behaviour!

Spoofing HTTP Referrer data using ASP.NET

Answers on here and various other sites are often full of warnings not to trust HTTP Referrer headers because they are 'so easily' spoofed or faked.
Before I go any further - no, I'm not up to no good - but I do want to run some referrer-dependant tests.
Whilst I don't doubt that the warnings about fake referrers are true, I can't really find much detailed info on how they can be manipulated. Even the Wikipedia article only talks about it in general terms.
I'm about to play with the RefControl addin for FireFox.
Programatically (in ASP.NET specifically) the UrlReferrer is a read-only property, so I don't see how I can fire off requests with fake referrer data if I can't set it? Do I really have to do it manually?
How would I use ASP.NET to send a request to my site with a user-supplied variable to populate the referrer header?
EDIT : As per my comment below, I ideally want to take an incoming request, manupulate the referrer data and then pass the request on to another page, intact. If I can make it appear intact by building a new one from scratch and copying the original properties, then that is fine too.
I don't know if this exactly what you want, but in general, you should be able to spoof the value of the UrlReferer property (even if it's read-only) in HttpContext.Current.Request by using a bit of reflection.
For example:
FieldInfo fi = HttpContext.Current.Request.GetType().GetField("_referrer", BindingFlags.NonPublic | BindingFlags.Instance);
string initialReferer = HttpContext.Current.Request.UrlReferrer.ToString();
if (fi != null)
fi.SetValue(HttpContext.Current.Request, new Uri("http://example.com"));
string fakedReferer = HttpContext.Current.Request.UrlReferrer.ToString();
On VS; these are the values before and after changing the UrlReferrer:
initialReferer
"http://localhost/Test/Default.aspx"
fakedReferer
"http://example.com/"
If you open the System.Web assembly using ILSpy you'll notice that the UrlReferrer property looks something like this:
public Uri UrlReferrer
{
get
{
if (this._referrer == null && this._wr != null)
{
string knownRequestHeader = this._wr.GetKnownRequestHeader(36);
if (!string.IsNullOrEmpty(knownRequestHeader))
{
try
{
if (knownRequestHeader.IndexOf("://", StringComparison.Ordinal) >= 0)
{
this._referrer = new Uri(knownRequestHeader);
}
else
{
this._referrer = new Uri(this.Url, knownRequestHeader);
}
}
catch (HttpException)
{
this._referrer = null;
}
}
}
return this._referrer;
}
}
This likely isn't going to get you what you want. But you can edit the Referror of an HttpWebRequest. I don't think there is a way of editing the referrer of your request in context.
using System.Net;
HttpWebRequest Req= (HttpWebRequest)System.Net.HttpWebRequest.Create("http://somewhere.com/");
Req.Referer = "http://www.fakesite.com";

cookie isn't updated until page refresh... how to avoid that?

I have some asp.net pages that read and write cookie values. During the life cycle of a page it may update the cookie value and then need to read it again further in the code. What I've found is that it's not getting the latest value of the cookie until a page refresh. Is there a way around this? Here's the code I'm using to set and get the values.
public static string GetValue(SessionKey sessionKey)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[cookiePrefix];
if (cookie == null)
return string.Empty;
return cookie[sessionKey.SessionKeyName] ?? string.Empty;
}
public static void SetValue(SessionKey sessionKey, string sessionValue)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies[cookiePrefix];
if (cookie == null)
cookie = new HttpCookie(cookiePrefix);
cookie.Values[sessionKey.SessionKeyName] = sessionValue;
cookie.Expires = DateTime.Now.AddHours(1);
HttpContext.Current.Response.Cookies.Set(cookie);
}
What you're missing is that when you update the cookie with SetValue you're writing to the Response.Cookies collection.
When you call GetValue you're reading from the Request.Cookies collection.
You need to store the transient information in a way that you access the current information, not just directly the request cookie.
One potential way to do this would be to writer a wrapper class that with rough psuedo code would be similar to
public CookieContainer(HttpContext context)
{
_bobValue = context.Request.Cookies["bob"];
}
public Value
{
get { return _bobValue; }
set {
_bobValue = value;
_context.Response.Cookies.Add(new Cookie("bob", value) { Expires = ? });
}
}
I ran into needing to do similar code just this week. The cookie handling model is very strange.
Start using Sessions to store your information, even if it's only temporary.
Cookies rely on a header being sent to the browser before the page has rendered. If you've already sent information to the client then proceed to set a cookie, you're going to see this "page refresh delay" you've described.
If it's necessary to have this value, use a session variable between the time you set the cookie and when you refresh the page. But, even then I would just recommend avoiding settings cookies so late in the processing step and try to set it as early as possible.

ASP MVC Cookies not persisting

I have a ASP MVC App with some seemingly simple code to save and retrieve cookies but for some reason they won't persist. The code in the controller is :
if (System.Web.HttpContext.Current.Response.Cookies["CountryPreference"] == null)
{
HttpCookie cookie = new HttpCookie("CountryPreference");
cookie.Value = country;
cookie.Expires = DateTime.Now.AddYears(1);
System.Web.HttpContext.Current.Response.Cookies.Add(cookie);
}
And to load it again :
if (System.Web.HttpContext.Current.Request.Cookies["CountryPreference"] != null)
{
System.Web.HttpContext.Current.Request.Cookies["CountryPreference"].Expires = DateTime.Now.AddYears(1);
data.Country = System.Web.HttpContext.Current.Request.Cookies["CountryPreference"].Value;
}
For some reason the cookie is always null?
The problem lies in following code:
if (System.Web.HttpContext.Current.Response.Cookies["CountryPreference"] == null)
When you try to check existence of a cookie using Response object rather than Request, ASP.net automatically creates a cookie.
Check this detailed post here: http://chwe.at/blog/post/2009/01/26/Done28099t-use-ResponseCookiesstring-to-check-if-a-cookie-exists!.aspx
Quote from the article in case the link goes down again ....
The short explanation, if you don’t
like to read the entire story
If you use code like “if
(Response.Cookies[“mycookie”] != null)
{ … }”, ASP.Net automatically
generates a new cookie with the name
“mycookie” in the background and
overwrites your old cookie! Always use
the Request.Cookies-Collection to read
cookies!
[ More detail in the article ]
In resume, don't use "Response" to read cookies, use "Request".

Resources