Difference between Session and HttpContext.Current.Session - asp.net

What is the difference between Session and HttpContext.Current.Session object?

A little late here, but here's something I just discovered.
#Phillipe Leybaert and #CSharpAtl are both incorrect. HttpApplication's Session property exhibits different behaviour than does that of the property HttpContext.Current.Session. They will both return a reference to the same HttpSessionState instance if one is available. They differ in what they do when there is no instance of HttpSessionState available for the current request.
Not all HttpHandlers provide session state. To do so, the HttpHandler must implement [one or both?] the marker interfaces IRequiresSessionState or IReadOnlySessionState.
HttpContext.Current.Session simply returns null if there is no session available.
The HttpApplication's implementation of the Session property throws an HttpException with the message Session state is not available in this context. rather than returning a null reference.
Some examples of HttpHandler that do not implement session are the default handlers for normally static resources, such as image and CSS files. Any reference to the HttpApplication's Session property in such cases (as in global.asax event handlers) will result an HttpException being thrown.
Needless to say, the unexpected HttpException provides a WTF?! moment if you're not expecting it.
The Session property of the HttpApplication class is implemented thus (from Reflector):
[Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public HttpSessionState Session
{
get
{
HttpSessionState session = null;
if (this._session != null)
{
session = this._session;
}
else if (this._context != null)
{
session = this._context.Session;
}
if (session == null)
{
throw new HttpException(SR.GetString("Session_not_available"));
}
return session;
}
}

There is no difference.
The getter for Page.Session returns the context session.

Nothing. Session just points to the HttpContext.Current.Session.

Internally, Page.Session points to It's HttpContext.Current.Session only, but there are still two differences depending on from where it's called.
Page.Session can be accessed only from classes inherited from System.Web.UI.Page and it will throw HttpException when accessed from WebMethod. Where as HttpContext.Current.Session can be accessed from anywhere as long as you're running in the context of a web application.
Other important difference where you can access Page.Session but cannot access HttpContext.Current.Session : If there is a method named GetData in your page(inherited from System.Web.UI.Page) which is executed concurrently in different threads from some other page method, GetData method can access the Page.Seession, but you cannot access HttpContext.Current.Session. It's because GetData has been called from different thread so HttpContext.Current is null and HttpContext.Current.Session will throw null reference exception, but Page.Session will still be attached with page object so page method GetData can access the Page.Session.

Related

System.Web.HttpContext.Current nulls itself after checking for a Cache

I encountered a weird issue today which made no sense to me. Here is a summary:
Inside a method, I check for a cached item as below:
private async Task<RatesStatus> getRatesStatusAsync() {
//...
if (_currentHttpContext != null) {
//Here, I am checking for a Cached item
var cachedRatesStatusObj = HttpContext.Current.Cache[Constants.RATESSTATUS_CACHE_KEY_NAME];
if (cachedRatesStatusObj != null)
return (RatesStatus)cachedRatesStatusObj;
}
//...
cacheRatesStatusObject(ratesStatus);
//...
}
Here, the HttpContext.Current is not null as expected inside an ASP.NET application. Then, inside the cacheRatesStatusObject method, I check if HttpContext.Current is null or not as below:
private void cacheRatesStatusObject(RatesStatus ratesStatus) {
//...
//Seeing if HttpContext.Current is null or not first.
//and it is null here...
if (HttpContext.Current == null)
return;
//...
}
And it is null there. No idea what is happening here. Any thoughts?
When you use async/await, the thread handling the request marks the request as incomplete and then returns to the ASP.NET thread pool. When the awaitable completes later, another thread is assigned to run the rest of the method, however HttpContext is not migrated across threads, that's why you get null reference when calling await method.
You can pass a reference of the HttpContext to the await method, something like this:
await cacheRatesStatusObject(HttpContext.Current, ratesStatus);
However you should be very careful dealing with concurrency and race conditions, for example if the await thread locks a resource and another request thread attempts to use it then your thread pool goes boom. Most people resolve this by creating new objects and passing them into paramaterized threads instead of passing a reference of HttpContext across threads.
Passing the instance sucks.
Use the .NET 4 MemoryCache classes instead.
http://stevescodingblog.co.uk/net4-caching-with-mvc/
It does not null itself.
The HttpContext is only stored in a 'thread static' way.
As suggested by the other answer, just pass the instance.

ASP.NET MVC: User.Identity.Name not available even when page is authenticated

I've been receiving some error reports recently that seem to suggest that sometimes User.Identity.Name is NULL or different to what it should be (the authenticated user's username), even when the page is authenticated:
[Authorize]
[HttpGet]
public ActionResult MyAction()
{
string username = User.Identity.Name;
Member member = memberRepository.GetMemberByUserName(username);
member.something // fails with a null reference exception
}
The GetMemberByUserName() method uses Linq to SQL to retrieve the member.
public Member GetMemberByUsername(string username)
{
if (String.IsNullOrEmpty(username))
return null;
return db.Members.SingleOrDefault(d => d.username.Equals(username));
}
Under which circumstances would this happen? Do I need to check if User.Identity.Name is NULL whenever I use it?
Of course, the User.Identity.Name could be a red herring, and it could be that the database is just not returning anything. I would probably have expected an exception to be thrown if this was the case, though.
EDIT:
This is an intermittent issue - it could be that an authenticated user refreshes once, the User.Identity.Name is correct and the member is retrieved, and then on a second refresh, the member is not retrieved.
it could be that the database is just not returning anything. I would probably have expected an exception to be thrown if this was the case, though.
No, it won't. SingleOrDefault will return a single record, no record, or throw an exception if more than one record exists.
Single will return a single record, or throw an exception if no record or more than one exists.
Could be a few things. Maybe you have case sensitivity issues with the String.Equals.
It's still possible that Request.IsAuthenticated (what [Authorize] looks at) is true, but there is no identity. Particulary true in custom authentication systems (such as attempting to decrypt the forms authentication ticket), and you haven't specified what your using.
Also, make sure the Username field is backed by a unique index, to provide server-side guarantees that SingleOrDefault will NEVER throw an exception.
I would put some try/catch in your controller actions, and setup ELMAH to catch the exceptions.
How about:
public Member GetMemberByUsername(string username)
{
if (String.IsNullOrEmpty(username))
return null;
return db.Members.SingleOrDefault(d => d.username.Equals(username));
}

Abstracting HttpContext Request and Session - thread safety

I have the following assemblies in my ASP.NET app:
Website - this is an ASP.NET website
ClassLib - this is just a class lib that contains all the business logic
Class Lib needs to interact with the HttpContext Session and Request objects. This is a code upgrade from an old ASP app, where I've hoovered all the VBScript that contained the logic and put it into VB.NET. We simply didn't have time to rewrite.
Instead of ClassLib interacting directly with HttpContext, which I thought was BAD and also prevented us from unit testing, I introduced the following abstraction layer:
Public Class Request
Private Shared _requestWrapper as IRequestWrapper
Public Shared ReadOnly Property RequestWrapper()
Get
If _requestWrapper Is Nothing Then
Throw New Exception("_requestWrapper is null. Make sure InitRequest() is called with valid parameters")
End If
Return _requestWrapper
End Get
End Property
Public Shared Sub InitRequest(ByRef requestWrapper As IRequestWrapper)
_requestWrapper = requestWrapper
End Sub
Public Shared Function GetVal(ByVal key As String) As Object
Return RequestWrapper.GetVal(key)
End Function
etc.
This means in the unit tests I can supply my own MockRequest object into this Request class, which is just a simple NameValue collection. The code in the ClassLib and the Website then simply use the Request class and are none the wiser that it isn't coming from the HttpContext, but rather this mock class.
When it comes to the real deal, I simply have the following (C#) class:
public class RealRequest : IRequestWrapper
{
public void Initialize(HttpContext context)
{
}
#region Implementation of IRequestWrapper
public object GetVal(string index)
{
return HttpContext.Current.Request[index];
}
etc.
This is initialised in Session_Start of global.asax in the Website, as follows:
protected void Session_Start(object sender, EventArgs e)
{
IRequestWrapper requestWrapper = new RealRequest();
WebSession.Request.InitRequest(ref requestWrapper);
}
I think this is similar to the Static Gateway pattern.
Now, I am aware of singletons and static vars in a multi threaded environment such as ASP.NET, but this is slightly different. When it gets down to the RequestWrapper.GetVal(), its actually going to the HttpContext for that running thread - and pulling the value from that.
Certainly, any concurrent tests that we do with multiple users hitting the same server have never shown up any strange behaviour.
I'm just looking for re-assurance that this is a sound design, and if not why not?
Thanks
Duncan
This is fine. We have a very similar case in our applications that either uses HttpContext if it exists or fake implementations otherwise.
The one thing to watch out for is that there is a very specific instance where HttpContext.Current will return a value but HttpContext.Current.Request will throw an exception when triggered by the Application_Start event. In framework code, you really don't know (or want to know) what triggered the call though.
Workaround for HttpContext.HideRequestResponse being internal? Detect if HttpContext.Request is really available?

explain why an object has lifetime outside scope

I've written a class as follows. I've written it taking into consideration that its mainly for use on the web (i.e. it will be used from aspx pages).
public class TestHelper
{
public TestHelper()
{
HttpContext ctxt = HttpContext.Current;
IHttpHandler RequestHandler = ctxt.Handler;
Page CurrentPage;
CurrentPage = (Page)RequestHandler;
CurrentPage.Unload += new EventHandler(CurrentPage_Unload);
Debug.Print("Open all connection here...");
}
void CurrentPage_Unload(object sender, EventArgs e)
{
Debug.Print("Close all connection here...");
}
}
And I've written my aspx page's code behind like this:
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
TestHelper helper = new TestHelper();
helper = null;
}
}
In spite of assigning helper to 'null' I find that CurrentPage_Unload() gets executed. Why is this behaviour so? What is this behaviour generally called?
The reason why I've written the class in that style was because I thought I could best manage my db connections in a central fashion in the class. Usually people would call methods on the object like helper.IsValid() followed by helper.ProfileExists() in the aspx code behind. Each of those methods would have their own db connection objects(IDbConnection), and their corresponding Open() & Close() calls to open/close db connection. I just felt that we should only do this only once in code. Hence I used the constructor to open db connections, and the Page object's unload event to close the connection objects. Are there any pitfalls to writing classes this way?
What is happening is you're attaching a delegate to the Unload event of the page. Even after your variable has been set to null, your page still exists and still has an Unload event which still holds a reference to the delegate you added to it.
To remove a delegate you need to use -= syntax.
CurrentPage.Unload -= new EventHandler(CurrentPage_Unload);
Assigning null to a variable does not end its actual lifetime. Because .NET uses a non-deterministic garbage collection system (where objects are periodically purged based on several criteria, rather than as soon as they fall out of scope), you cannot rely on an object ever being collected before the process that created it ends.
Furthermore, because you're attaching an event handler (meaning a delegate, which includes a reference to your newly-constructed instance) to another object, you're extending the viable lifetime of your object as well. As long as that event handler is attached, your object cannot be collected until the object it's attached to is eligible.
You have to think about what happens when you execute the line
helper = null;
You simply have a reference to an object. When you assign that object to null, you're simply setting your reference to null. Nothing has happened to the object. Consider the following code:
var first = new object();
second = first;
first = null;
Would second now be null? You can think of a reference as simply a number - it's simply the address of the object in memory.
The .NET garbage collector simply looks at objects and checks if there are any references to that object. If not, it will remove that object.

How to create singleton Page in asp.net

We can use a class implement IHttpHandlerFactory to override or intercept the create progress of Page's instance
In a word we can use:
PageHandlerFactory factory = (PageHandlerFactory)Activator.CreateInstance(typeof(PageHandlerFactory), true);
IHttpHandler handler = factory.GetHandler(context, requestType, url, pathTranslated);
return handler;
to create new instance of asp.net page object.
But you know, the page is not in persistence
If you save the object in applicationstate or session, when next request, you can get the page,but you will find the Application(HttpApplication) in "Page.Context" is null.
In that, the page visit will fail and it cannot be a singleton one.
How to set the httpApplication?
I don't understand all of your question, but I guess you are looking for HttpContext.Current.Application
Use that instead of Page.Context.Application.
I think that you need to call the internal protected FrameworkInitialize() function after the page has been constructed.

Resources