Maintain the SessionID for Entire Application in ASP.NET - c#

I am implementing the Ecommerce projects, where I need to static SessionID, is there any way to maintain the SessionID in the Entire Application.Explanation of my question is here
session.sessionid in asp.net?
but How can I implement this approach.

Now I understand your point
you have to do something like this on the Global.asax file
protected void Session_Start(Object sender, EventArgs e)
{
Session["DummyData"] = "dummy";
}
Adding any value to the Session object at the very first moment after created, you avoids to get different SessionIDs because the Session object wasn't accessed yet.
EDIT
Anyway checking your last comment I don't see that this is something that is affecting your development in some way. Probably you're over thinking on this. If you just need to avoid users to buy more than X products, you don't care about this problem. When the first product is added to the session, the same SessionID will be used in successive requests, until it expires.

Reading the other post you mention, it sounds like either Session was not being used, and so a new Session ID was generated on each request. To fix this, just store something (anything) in the session on the first request to make sure it sticks.
Session["something"] = "anything";
Or, it could be that the user did not allow cookies, which would also cause a new session on each request. So, your users need to allow cookies.
Or you could use cookie-less session.
The other post explains it pretty well, I think.

Related

Best practice to avoid double request from View in ASP.NET

I have the following controller:
[HttpPost]
public ActionResult SomeMethod(string foo, obj bar)
{
//Some Logic
}
Now suppose that from the view that Action is called from a Button or from Ajax (with some edits), and I don't want to receive a double request.
What is the best approach to handle it from server side?
Update
You'd first have to define the time interval that would meet the
criteria of a double request – Jonesopolis
Let's suppose that in this case a double request are when the difference of time between first and 2nd call is less than 1s
Frankly, you can't, at least not totally. There's certain things you can do server-side, but none are fool-proof. The general idea is that you need to identity the POST is some way. The most common approach is to set a hidden input with a GUID or similar. Then, when a request comes in you record that GUID somewhere. This could be in the session, in a database, etc. Then, before processing the request, you check whatever datastore you're using for that GUID. If it exists, it's a duplicate POST, and if not, you can go ahead.
However, the big stipulation here is that you have to record that somewhere, and do that takes some period of time. It might only be milliseconds, but that could be enough time for a duplicate request to come in, especially if the user is double-clicking a submit button, which is most often the cause of a double-submit.
A web server just reponds to requests as they come in, and importantly, it has multiple threads and perhaps even multiple processes serving requests simultaneously. HTTP is a stateless protocol, so the server doesn't care whether the client has made the same request before, because it effectively doesn't know the client has made the same request before. If two duplicate requests are being served virtually simultaneously on two different threads, then it's a race to see if one can set something identifying the other as a duplicate before the other one checks to see if it's a duplicate. In other words, most of the time, you're just going to be out of luck and both requests will go through no matter what you try to do server-side to stop duplicates.
The only reliable way to prevent double submits is to disable the submit button on submit using JavaScript. Then, the user can effectively only click once, even if they double-click. That still doesn't help you if the user disables JavaScript, of course, but that's becoming more and more rare.
Look. Becareful with this approach. You will add most complexity to control this in server side.
First, you need recognize when the multiple requests are comming from the same user.
I don't think that to control this in server side is the best way.
However, if you really want that... look: https://stackoverflow.com/a/218919/2892830
In this link was suggested maintain a list of token. But, in your case, just check if the same token was received more than one time.
You need at least to implement double click on event listener.
UseSubmitBehiviar="false"
OnClientClick="this.disable='true'; this.value="Please wait";"
Check ASP.NET Life cycle
Check Request/Redirect
Add test code to see who is responsible
if (IsPostBack)
{
_CtrlName = thisPage.Request.Params.Get("__EVENTTARGET");
if (_CtrlName != null && _CtrlName == myButton.ID)
{
//Do your thing
}
}
Check IsPostBack in page load and use it correct to prevent dublicate requests.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
}
}

Best way to prevent race conditions in a multi instance web environment?

Say you have an Action in ASP.NET MVC in a multi-instance environment that looks something like this*:
public void AddLolCat(int userId)
{
var user = _Db.Users.ById(userId);
user.LolCats.Add( new LolCat() );
user.LolCatCount = user.LolCats.Count();
_Db.SaveChanges();
}
When a user repeatedly presses a button or refreshes, race conditions will occur, making it possible that LolCatCount is not similar to the amount of LolCats.
Question
What is the common way to fix these issues? You could fix it client side in JavaScript, but that might not always be possible. I.e. when something happens on a page refresh, or because someone is screwing around in Fiddler.
I guess you have to make some kind of a network based lock?
Do you really have to suffer the extra latency per call?
Can you tell an Action that it is only allowed to be executed once per User?
Is there any common pattern already in place that you can use? Like a Filter or attribute?
Do you return early, or do you really lock the process?
When you return early, is there an 'established' response / response code I should return?
When you use a lock, how do you prevent thread starvation with (semi) long running processes?
* just a stupid example shown for brevity. Real world examples are a lot more complicated.
Answer 1: (The general approach)
If the data store supports transactions you could do the following:
using(var trans = new TransactionScope(.., ..Serializable..)) {
var user = _Db.Users.ById(userId);
user.LolCats.Add( new LolCat() );
user.LolCatCount = user.LolCats.Count();
_Db.SaveChanges();
trans.Complete();
}
this will lock the user record in the database making other requests wait until the transaction has been committed.
Answer 2: (Only possible with single process)
Enabling sessions and using session will cause implicit locking between requests from the same user (session).
Session["TRIGGER_LOCKING"] = true;
Answer 3: (Example specific)
Deduce the number of LolCats from the collection instead of keeping track of it in a separate field and thus avoid inconsistency issues.
Answers to your specific questsions:
I guess you have to make some kind of a network based lock?
yes, database locks are common
Do you really have to suffer the extra latency per call?
say what?
Can you tell an Action that it is only allowed to be executed once per User
You could implement an attribute that uses the implicit session locking or some custom variant of it but that won't work between processes.
Is there any common pattern already in place that you can use? Like a Filter or attribute?
Common practice is to use locks in the database to solve the multi instance issue. No filter or attribute that I know of.
Do you return early, or do you really lock the process?
Depends on your use case. Commonly you wait ("lock the process"). However if your database store supports the async/await pattern you would do something like
var user = await _Db.Users.ByIdAsync(userId);
this will free the thread to do other work while waiting for the lock.
When you return early, is there an 'established' response / response code I should return?
I don't think so, pick something that fits your use case.
When you use a lock, how do you prevent thread starvation with (semi) long running processes?
I guess you should consider using queues.
By "multi-instance" you're obviously referring to a web farm or maybe a web garden situation where just using a mutex or monitor isn't going to be sufficient to serialize requests.
So... do you you have just one database on the back end? Why not just use a database transaction?
It sounds like you probably don't want to force serialized access to this one section of code for all user id's, right? You want to serialize requests per user id?
It seems to me that the right thinking about this is to serialize access to the source data, which is the LolCats records in the database.
I do like the idea of disabling the button or link in the browser for the duration of a request, to prevent the user from hammering away on the button over and over again before previous requests finish processing and return. That seems like an easy enough step with a lot of benefit.
But I doubt that is enough to guarantee the serialized access you want to enforce.
You could also implement shared session state and implement some kind of a lock on a session-based object, but it would probably need to be a collection (of user id's) in order to enforce the serializable-per-user paradigm.
I'd vote for using a database transaction.
I suggest, and personally use mutex on this case.
I have write here : Mutex release issues in ASP.NET C# code , a class that handle mutex but you can make your own.
So base on the class from this answer your code will be look like:
public void AddLolCat(int userId)
{
// I add here some text in front of the number, because I see its an integer
// so its better to make it a little more complex to avoid conflicts
var gl = new MyNamedLock("SiteName." + userId.ToString());
try
{
//Enter lock
if (gl.enterLockWithTimeout())
{
var user = _Db.Users.ById(userId);
user.LolCats.Add( new LolCat() );
user.LolCatCount = user.LolCats.Count();
_Db.SaveChanges();
}
else
{
// log the error
throw new Exception("Failed to enter lock");
}
}
finally
{
//Leave lock
gl.leaveLock();
}
}
Here the lock is base on the user, so different users will not block each other.
About Session Lock
If you use the asp.net session on your call then you may win a free lock "ticket" from the session. The session is lock each call until the page is return.
Read about that on this q/a:
Web app blocked while processing another web app on sharing same session
Does ASP.NET Web Forms prevent a double click submission?
jQuery Ajax calls to web service seem to be synchronous
Well MVC is stateless meaning that you'll have to handle with yourself manually. From a purist perspective I would recommend preventing the multiple presses by using a client-side lock, although my preference is to disable the button and apply an appropriate CSSClass to demonstrate its disabled state. I guess my reasoning is we cannot fully determine the consumer of the action so while you provide the example of Fiddler, there is no way to truly determine whether multiple clicks are applicable or not.
However, if you wanted to pursue a server-side locking mechanism, this article provides an example storing the requester's information in the server-side cache and returns an appropriate response depending on the timeout / actions you would want to implement.
HTH
One possible solution is to avoid the redundancy which can lead to inconsistent data.
i.e. If LolCatCount can be determined at runtime, then determine it at runtime instead of persisting this redundant information.

Static Dictionary<T,T> sharing information accross sessions. How to stop this?

In my web project, I am using Static List. So say suppose I have 2 users (A, B) logged in to my website at the same time, then this List will store some information about A and as well as B. But say when I process B List's records, A's List's are getting processed instead of B's.
Can somebody point out the problem please?, also please suggest me some possible solution to avoid this problem.
I am using ASP.NET C# 3.5.
Thank you in advance :)
Edit:
Now I have changed the data type from Dictionary to List, but still the same problem...
A static variable is one that is the same for all instances of a particular class. So this means your website uses the exact same dictionary for User A, B, C, D, etc. Essentially whichever user last writes to the dictionary is the one whose content you will see, regardless of which user is looking.
As other's have suggested, you can use Session variables. These are stored in the server's memory, and are related to a specific browser 'session' (i.e. user).
Personally, I prefer to use the ViewState as this is stored in the response to the browser, and returned to you whenever the page makes a postback. This means less memory usage on the server, the viewstate is not volatile across sessions (or subject to application resets like session). However this also means that whatever you are storing is sent across the wire, so you would never want to store things like credit card numbers, SSN's, etc.
It also means that if you're storing a lot of very large objects, you're going to have a very large response and postback (possibly slowing the cycle), so you have to be more careful about how and what you store.
So that's a few different options for you, you should do the research and decide which is best for your requirements.
Storing values in session is like:
Session["mykey"] = value;
And reading values from session is like:
Object value = Session["mykey"];
The session will time out after a couple of minutes and the value would then be null.
To avoid this consider using:
Viewstate["mykey"] = value;
Viewstate is used exactly like session except that the value has to be serializable.
The viewstate is send to the client and back again so consider the amount of data that you want to store this way. The viewstate is stored in "__VIEWSTATE" and encoded in base64.
Don't use a static dictionary. Use Session variables to store information about a user's session.
For better information, you will have to provide us with a bit more information: what records? in what format? etc.
When a variable is declared static, that means there is exactly 1 instance of that variable per class (this also includes classes in web applications).
Thus, a static variable is not tied to a user. If you need to store data specific to a user, consider using a Session variable.
You could store the dictionary in the Session, that way each user would have their own and the code wouldn't have access to others.
Or if you sometimes want to be able to access other users' info, you could declare it as
static Dictionary<String, Dictionary<T, T>>
where the string key is the unique user id.

Manually create/populate .NET Session object

First a brief background. I am using .NET output caching and substitution controls to keep a few bits updated on each page refresh. The static methods that the substitution controls use require access to the Session object. Unfortunately, the HttpContext session is null in those methods.
I'm not going to rewrite my app to use a different store than the Session. Session is perfect for everything I need except this one aspect.
Can I manually create or populate a session object or otherwise get at its data by some sort of black magic wizardry? The session cookie is still being set from the client to the server. The info has got to be there somewhere. How do I get at it?
I'm not convinced this is a "good" way to go...but you can very dodgily store a reference to the Session in a shared/static variable and access it then.
Public Class SessionHelper
Public Shared TheSession As HttpSessionState
End Class
In your Session Start event (haven't figured out the best place to put it yet as the session isn't available in Application start as far as I am aware)
Sub Session_Start(ByVal sender As Object, ByVal e As EventArgs)
' Store a reference...only do this once etc etc
If SessionHelper.TheSession Is Nothing Then
SessionHelper.TheSession = HttpContext.Current.Session
End If
End Sub
Then in your code you can just reference the helper
Dim someVariable as String = SessionHelper.TheSession.Item("ItemName")
A few things I'm not sure about this method:
not sure if the session object is now not thread safe
it doesn't seem quite right
this example is extremely simple...
Edit
I verified this worked for me by adding something to the cache and seeing if the session was available in the Cache Remove Callback which Http.Context.Current is not available in.
Edit 2
Here's a screenshot of it correctly returning the value. So it must be working to some degree, but the fact that the SessionId is not set is kind of worrying...I know I've used this technique before to access the Cache object but the cache is the cache, where as the session does need something to identify each session...Here you go anyway:
Session information is stored in the server's memory. You can, however, configure ASP.NET to store the session information inside SQL Server.
HttpContext.Current.Session should give you access to the current Session. The only time when this would not work is when there is no current HttpContext. As long as you have a reference to System.Web, it should work.

Beginner how do you maintain state in an ASP C# Web Page

Update: the clearest explanation I have found on the web as I have been struggling through this can be found here.
Maybe I just don't understand the model of runat server terribly well. It appears the following code is always executing the if block. If the code is running on the server side I guess I can understand that it has to be stateless.
I am a seasoned non-web programmer but it appears counter intuitive to me. Will I need to create some sort of session object or pass the current state along in the URL or what?
<script runat="server">
DateTime begin;
DateTime end;
int iSelectedStart = 0;
int iSelectedEnd = 0;
int iPutName = 0;
protected void Button1_Click(object sender, EventArgs e)
{
if (iPutName == 0)
{
iPutName = 1;
Label1.Text = TextBox1.Text + " you will be slecting your start and end dates.";
It looks like part of your code got cut off, but here's the basic thing with web programming -- it's stateless. Unless, that is, you do something (use ViewState, Session, etc.) to add some state into the mix.
In your case, it looks like you want to maintain some state through refreshes of the page. Put the values you want to preserve in ViewState to keep them across postbacks to the same page. If you want to hold values across pages on your site, use Session. If you want to maintain values across visits to the site, put them in a database and tie them to a login or cookie.
The important thing to remember here is that the web is stateless. Each request from a person's browser is completely separate from all previous requests. What's happening with your code is that the class is being instantiated from scratch each time the client requests a page. That includes clicking Button1.
If you want values to persist between requests, you have to store it in a location where it can be retrieved later. The Session object provides this for you.
Basically, you'll need to store the iPutName variable in the session somehow. Probably the nicest way is to encapsulate it in a property:
protected int iPutName
{
get {
if (Session["iPutName"] == null)
Session["iPutName"] == 0;
return Session["iPutName"];
}
set { Session["iPutName"] = value; }
}
Edit: The ViewState object will work as well (as long as ViewState is turned on on the page). This encodes the value in a hidden field in the HTML and decodes it when it comes back.
Edit (again): Apologies for repeated edits, but I should clear this up. What Jonathan and Emil have said is correct. You should probably be using ViewState for this rather than Session unless you want this value to remain accessible between pages. Note that this does require that ViewState is turned on and it will result in a larger payload being sent to the client.
I really recommend to look at the quick start tutorial.
http://quickstarts.asp.net/QuickStartv20/aspnet/Default.aspx
There are a lot of concepts in dot net to simulate state on the UI.
In your case I think what you really want to do is using viewstate. Sessions should be used with care and I think the concept you are looking for i localized to the page not to the entier user session.
You should also look at the concept codebehind/codefront as well.
Because ASP.NET is stateless what you're assuming is correct. The postback will cause the page to lose the variable for iPutName. Storing in session is one option, or storing in viewstate could be another option.
The main thing to understand here is how the ASP.NET page lifecycle works and what happens each time you post back to the server.
For the lifecycle, check out the following URL :
http://www.eggheadcafe.com/articles/20051227.asp
You can store your iPutName in the session by doing this :
Session["iPutName"] = iPutName;
Fetching the session variable is also easy, but you should be sure to do a NULL check, like this:
if (Session["iPutName"] != null) iPutName = Session["iPutName"];
Haven't tested any of this, but if you encounter typos... sorry ;)
The Url you posted in your update is definitely not "All You Want to Know" about ViewState.... not even close. I only scanned his article but he doesn't appear to address Page Life Cycle at all. If your going the View State route then read these 2 links:
Understanding ASP.NET View State by Scott Mitchell
Truly Understanding ViewState By Dave Reed
If you're new to ViewState then dump all that guff (1 half the article) about parsing ViewState mentioned in your linked article. It's simply not required for anything but highly specialized scenarios. It is definitely not a normal thing to be doing re:ViewState.

Categories