Cost of accessing session value - asp.net

Is there a cost to accessing a session value? Apart from the cost of accessing a (I presume) dictionary. Maybe a session deserialize every time it's being accessed.
For example, I've seen some people put the session value in a variable.
_sessionValue = CType(Session(SESSION_NAME), SomeClass)
_sessionValue.SomeFunction1()
_sessionValue.SomeFunction2()
And others create a property
Public ReadOnly Property SessionValue As SomeClass
Get
Return CType(Session(SESSION_NAME), SomeClass)
End Get
End Property
SessionValue.SomeFunction1()
SessionValue.SomeFunction2()
I wonder if there is a significant difference in speed between the two or if one is recommended from the other.

Couple of things here. First, those code samples are doing nothing more than casting the session object to a type. This would be done anyway in the code using the object. The benefit is that there is a page property that you can easily use in any method. The session object won't be read and cast as the type unless you make a call to the property.
You should decide for yourself if you want to use a private or public member. There isn't really any difference between the property and the member.
You can read up on making session state fast here.
For details on seralizing and deserializng the session objects check this older post.

Related

Type Safe Coding

When i started developing web applications i stored the authentication details of the user in two session variables
Session["UserName"]="username";
Session["Password"]="paswword-123";
But someone proposed me an idea to create a class which holds the UserName and Password properties and on succesful authentication i have been asked to create an instance of the class and set the UserName and Password properties and store that instance in the session.
I have been told that the session object is TypeSafe. Can someone explain what is typesafe coding and the advantage of storing the object in the session.
Basically, the classic approach of storing values directly in Session["something"] has two drawbacks:
Magic strings: If you mistype something, your code compiles fine but you get either a runtime error or, worse, an unnoticed bug in your code.
Casting: After reading Session["something"], you need to cast it to the type you need. (This is what is meant by "not type-safe".)
Using a strongly-typed object that is stored in the Session eliminated the second problem. Well, actually, your custom object still needs to be cast, but it's only one cast instead of two (or ten) casts, which reduces the likelyhood of something going wrong. Again, a wrong cast is something which is only detected at run-time.
Another approach is to encapsulate the access to Session variables in static properties:
public class MySession {
public static string UserName {
get { return (string)HttpContext.Current.Session["UserName"]; }
set { HttpContext.Current.Session["UserName"] = value; }
}
}
Of course, both approaches can be combined, allowing you to group related properties (UserName and Password) in a common object.
Having a User class with 2 fields can be good for many reasons, as for type safety, if you ever type Session["Pasword"] somewhere you will get an error that wont be so easy to find, you will have to check for both parameter names everywhere. You need them to be correct, and its a great source of errors. Once you store User object instead of 2 unconnected strings you will have be able to use type safe code like User.Password instead of trying to access password by string indexer in Session. Also if your user ever gets more fields , which is very common you will simply add them to User class, not start creating new parameters & names and store them in Session heap.
As for typesafe coding I think http://en.wikipedia.org/wiki/Type_safety should help, or any other type of article on topic which is very popular I think.
Also I dont think you should store password in session, depends on your program logic but usually password should only be used to compute its md5 hash and never be used afterwards.
Well you're friend is half right, but I don't believe Session is inherently type safe. The Session collection stores instances of Object. So you can store an instance of any type (a string, an int, or a custom login class) because they all derive from object. However, when you retrieve that object, you don't know what type it is, and need to carefully cast it, with exception handling, before you use it.
eg this works fine:
Session["UserName"] = "Freddy";
string theUserName = (string)Session["UserName"];
However you could try to do the following, which will cause errors.
Session["UserName"] new StrangeDataClass(); //Uh Oh, that's not a string.
string theUserName = (string)Session["UserName"]; //unexpected behaviour based on StrangeDataClass.ToString() implementation.
To work around this, you'd have to do the following:
string theUserName = Session["UserName"] as string;
if (string != null)
//The cast worked...
else
//The cast failed, (or the string stored in session was null)
Having a custom login object slightly solves this problem, because you'd only have one object to worry about, and one cast to make. You could also extend the login object easily with extra information, and still not have to do any more casts.

How to save value across postbacks for a composite control without using viewstate

I have a composite control that has a couple of private fields that reference values in the cache and these private fields are called during the constructor method. Since a string key is used to identify the value in the cache, I must have a way of storing that string key in such a way that it is available at the time the control is instantiated, and I have to be able to reference it on postbacks without it changing.
In addition, this key is generated the first time the control is loaded, but it should not be changed again after that first time.
How can I accomplish this?
I have already tried saving it to viewstate, but that doesn't work because viewstate is not yet available at the time the control is instantiated.
I have tried using a private field and then checking against Page.IsPostback in the constructor and if it isn't postback, I assign a value to the private field, but on subsequent postbacks it looses it's value, and I can't reassign it in the Page.IsPostBack again because it is an autogenerated GUID.
This has got to be something folks have had to do before....
There isn't a lot of state info available during control construction at all, so this could be difficult. Is there some reason you can't move your code which accesses the Cache'ed info into the control's Init event?
I assume you can't use Session because the information stored is related to that specific request/postback. If it's not specific to that request, using Session could be a possibility - but I think you may encounter other problems trying to deal with control state so early in the lifetime.
After seeing your comment to the other answer; you should be able to move your code that checks for the cached datasource into the control's Init or even Load event, so the state will be available.
Also, incidentally; are you sure you really need to cache this data? That could end up taking up a lot of server memory.
Have you tried Session?
You can store anything you like in the session object for one particular user, maintaining the value / object between postbacks.
If you want to store on a global basis and not per ser basis, try Application
Although this isn't the best solution (rearranging your logic to fit the lifecycle model generally is), have you tried accessing the Request directly? I once really wanted to get the selected value off a DropDownList very early in the lifecycle so I could adjust some elements in the building, and I did it like this:
myDropDownList.SelectedValue = Page.Request.Form[myDropDownList.UniqueID];
So instead of waiting for the viewstate to load the server-side proxie's values, I just got it myself from the client-side control value that was passed in on the post. I probably would do things differently if I redesigned that page, but it seems to have worked out alright for now and it solved the problem I was having.

Provide strongly typed access to the session object

What is the best way to provide strongly typed access to the session object? I am planning on turning on Option Strict, which is causing the compiler to complain about my lazy programming technique of directly accessing the session object:
Dim blah As Integer = Session("Blah")
My initial thought is to create a class that wraps the session and provides strongly typed properties for the information stored in the session. However, I cannot decide if the class should be a singleton, or instantiated on every use, or where the code should reside (i.e. within the web project or within a class library).
I'm leaning towards a singleton in my class library, but I don't know if that is the best solution, or if I am missing any other possibilities.
Proposed Solution:
Public Class SessionAccess
Public Shared Property Blah(ByVal session As HttpSessionState) As Integer
Get
Return Convert.ToInt32(session("Blah"))
End Get
Set(ByVal value As Integer)
session("Blah") = value
End Set
End Property
End Class
Code Behind:
Dim blah As Integer = SessionAccess.Blah(session)
I deleted my original answer as #Jason Berkan made a very good point when he questioned my answer. Jason, I think this idea is fine.
The only thing I would change in your code example is to check to ensure that the session variable exists.
Either my proposal is the "standard" way to do it, or else no one wraps their session access, since this question hasn't received very many answers.
I did find one line in this answer that mentioned creating a SessionManager:
Wrap the ASP.NET Session with a
SessionManager to avoid development
mistakes in spelling, etc. when
referencing items from Session.
I have not thought of any reason to not use a singleton class to provide typed access to the session, so that is the solution I went with in the project.

Need to store a static value for the duration of a request. How?

I have an ASP.NET MVC application. I have come to an idea of generating autoincremented values to be used as unique element ids. The question is, how can I have and work with a global variable which should be there for the duration of a request (page generation) but no longer?
I thought of using TempData for this shared variable and then just delete this key when the page is done. But then, where in code to purge this TempData key? Obviously it has to be some very last piece of code where the page has been rendered already.
Any input is highly appreciated.
EDIT: I have a number of HTML helpers that can be called from various views and partial views, so declaring a variable on a page and passing it to each helper is obviously not a good solution. I wish to just use the helpers and know they all are getting unique ids behind the scenes.
Okay, I have googled a little bit and found a solution on ASP.NET forums.
http://forums.asp.net/t/1401685.aspx
Obviously, I can use the HttpContext.Current.Items collection to have my little static variable for the duration of a request.
If all you need is to store a number, the resources that would take to manage its lifestyle would take a lot more than just having a one static integer and always reusing it.
Do not bother deleting the key after each request. Just use a static (I think this is shared in visual basic) integer, use and increment it every time you need a unique value. Also take its mod with a ridiculously high number each time to make sure it will not be reused in a single request and it will never overflow.
Why don't you define your integer variable at the top of the page view file?
Use it throughout the view rendering execution and at the end of it you can easily leave it as is. You don't have to explicitly destroy anything. Your variables live for the duration of request only. IIS is stateless service (if you subtract Session, Cache and Application variables) so it doesn't really remember anything explicitly.
I would imagine you could use the Application_BeginRequest and Application_EndRequest methods in global.asax.cs; Note I can't double check the method names currently, but I think they are close.
You could create a member variable in your controller which would be regenerated for each request:
public class ItemController : Controller
{
private int _UniqueID = 0;
public ActionResult Index()
{
foreach (var item in items)
{
item.UniqueID = _UniqueID++;
}
// etc...
}

Session Variable Member?

I'm using a compiled .dll provided by someone else -- I know little about it, other than it has a session variable that I must access in a way that is strange to me. Not sure what to call it -- have googled for words that I thought might be right, but so far no success. Here is what it looks like:
Session("receipt").username
It's the .username part that I don't understand. What is it? How is it created?
Thanks for any help.
Session is probably a global object which has a default property which returns a SessionItem object. The SessionItem object is loaded from the browser-session (probably) by the Session object. The SessionItem object has a property username, which is a value stored somewhere in the browser-session.
Some code to clear things up:
Public Class Session
Private Items As SessionItemCollection
Default Public ReadOnly Property SessionItem(ByVal id As String) As Object
Get
Return Me.Items.Find(id)
End Get
End Property
End Class
And you calling the code (Which searches for the "receipt" item in the SessionItemCollection Items from Session):
Session("receipt")
My first guess (since there isn't much other code to go off of) is that the object being stored in the session variable and accessed via Session("receipt") is of a class that contains a property or member called username which you are accessing in that fashion.
The basic idea is that Session("receipt") will pull back whatever this object is (for the sake of instruction we will say it is a receipt object) and the .username is referencing the username property of that receipt object.

Resources