Any issues using HTTPContext outside of web project - asp.net

We have a web application with access to Business logic and data access in separate projects.
The way it is designed, key values is never passed to data access layer or business logic. Instead business layer has a class which contains public read only property through which DAL layer access the values.
Business logic layer is in a different project. Web project gets the reference.
Business logic layer has this class : Public NotInheritable Class clsUserProfile
Which has this property:
Public ReadOnly Property AgencyCode() As Integer
Get
If clsAppInfo.IsWebApplication Then
If (HttpContext.Current.Session(_AgencyCodeKey) Is Nothing) Then
Return 0
Else
Return HttpContext.Current.Session(_AgencyCodeKey)
End If
Else
Return AgencyCodeWIN
End If
End Get
End Property
/** For windows Agency Code is declared as shared
Public Shared Property AgencyCodeWIN() As Integer
Get
Return _AgencyCodeWIN
End Get
Set(ByVal value As Integer)
_AgencyCodeWIN = value
End Set
End Property
/****
To determine whether it is a web app or not .......
Public Shared ReadOnly Property IsWebApplication() As Boolean
Get
If AppCodeWIN IsNot String.Empty Then
'Desk top App is required to pass AppInfo
Return False
Else
'Web App is default
Return True
End If
End Get
End Property
Will the data will be overwritten when multiple users login.
Many people say that it is not advisable, but cannot find any provable reason as to why it is not recommended?
If anybody can give clear reasons that would be great.
Thanks,
sandy .

Will the data will be overwritten when multiple users login
No
Many people say that it is not advisable, but cannot find any provable reason as to why it is not recommended?
In this context, adding a third running mode would be a pain.
In fact, your class clsUserProfile should not be aware of your application running mode (webapp or desktop). It even should not know about HttpContext and Session or choose between two running modes, just to get an AgencyCode.
clsUserProfile should be a plain C# object. The running mode should be handled at a higher level in your app.

Related

Create Unique Session Variable per Browser Window or Tab

Having a slight problem with creating a .Net Session based variable.
I know i can just use the Session extension and be done with it but i am looking more for a Multiple Browser (either Window or Tab, for IE) situation on a single desktop.
Currently, i have a Module declared in the Web-App and when i open up two individual Windows of IE they initially load the custom PageRouting design, as expected but once i go to the next step with both windows open, the last one to be opened is the design/logic used for the rest of the application.
Module.vb
Namespace classes
Module Globals
Public Brand As Brand
Public Test As Test
Public Results As Results
Public Primary As String = "#FFFFFF"
Public Secondary As String = "#FFFFFF"
Public Terteruary As String = "#FFFFFF"
End Module
End Namespace
In code, i reference the objects as Globals.Brand or Globals.Primary but in either case a situation where the same desktop could open up the same website with different PageRouting address, it assumes the last opened browser window.
The Brand & Test variables are initialized in the Session_Start event in Globals.asax. All references to these objects are explicit references using Globals.<variable> annotation when used. Results is initialized on first use during the execution of the website.
Question
How do i make sure that each individual browser window is loaded with its own unique session cache for use with the site?
Updated - 2012-12-03
What about a design like this?
Public Class Class1
private _sess as HTTPSessionState
...
private readonly property Session as HttpSessionState
Get
if _sess is nothing then
_sess = httpcontext.current.session
end if
return _sess
End Get
end property
...
public property Primary as string
Get
return cstr(session("primary"))
end get
Set(value as string)
session("primary") = value
end set
end property
...
end class
With Class1 being instantiated at the Master/Content page level?
Update #2 - 2012-12-03
Modified the module, let me know if this is a viable session control setup
Module Globals
'Dictionary Collection of type (SessionID:String, Quiz:classes.Quiz)
Public Quizzes As Dictionary(Of String, classes.Quiz)
Public Property Quiz(session As String) As Quiz
Get
Return Quizzes(session)
End Get
Set(value As Quiz)
Quizzes(session) = value
End Set
End Property
End Module
Final Form 2012-12-10:
Module.vb
Module Globals
'Get/Set a Quiz object into the SessionState.
Public Property Quiz(sess As HttpSessionState) As Quiz
Get
Return CType(sess("quiz"), Quiz)
End Get
Set(value As Quiz)
sess("quiz") = value
End Set
End Property
End Module
Web.config
<system.web>
...
<sessionState mode="InProc" cookieless="UseCookies"
regenerateExpiredSessionId="true" timeout="20"
cookieName="ASPNET_Quiz" />
...
</system.web>
The above form worked as expected utilizing the indexer aspect of a Property. Havent had any user instance problems. One side note, is that in order for this to work effectively the user must close all browser windows and open a new window for the session to clear out
The problem you are coming across is a very common one in web programming. A Module's members are static - meaning there is one instance of them across the entire AppDomain of your application. Every user that accesses these will get the same object.
You could possibly replace the public variable in your module with a property whose getter you write to access a user-specific field in a dictionary (please remember thread safety when writing this getter code).
The much easier solution would be to use the Session. Session values are stored server-side and are user specific. The only thing that get's sent client side is the session key, and if you are using .Net authentication, this is likely already getting sent.
Check this source:
How to get a public variable (in a Module) to NOT share value between users

How to get a public variable (in a Module) to NOT share value between users

I'm working in an ASP.NET (VB) Web Application with Windows/Active Directory Authentication
I am using a module so that I can call public subroutines and functions, and reference variables, without having to instantiate a new object to access them on each page.
Within that module, I have some Public variables that I am using in multiple pages throughout the web application. I've recently realized that the values for these public variables in the module get shared between all users.
THE GOAL:
I want the value for these global variables to be specific to a single user and not shared between all sessions, and I do not want to have to instantiate a new object/class on every page that uses the variable.
THE CATCH:
I don't want to store the value in a client-side variable such as a cookie or session. I want the value to be stored on the SERVER but specific to each client/user.
The only thing I can think to do is setup a global collection/dictionary and store the variables with the authenticated user names, but then I need to have specific functions to get and set the values. While this will work, it requires all the references to these variables on all pages in the application to be updated.
EXAMPLE OF THE PROBLEM:
The below code shows how I am creating the public variable within the module and how the value is being set from one page and used on another. I'd like to continue to use this variable in the same way and share it's value between pages, but the value of the variable needs to NOT be shared between users.
-- MODULE.VB --
Public Module MyMod
Public myVariable as String = ""
End Module
-- MAINPAGE.VB --
Partial Class _Default
Sub Page_Load() Handles MyBase.Load()
myVariable = "HELLO WORLD"
End Sub
End Class
-- NEXTPAGE.VB --
Partial Class _Default
Sub Page_Load() Handles MyBase.Load()
Response.Write(myVariable)
End Sub
End Class
There are a LOT of pages in this application that will need to be manually updated if I have to use my userID-indexed collection solution, so I'm hoping there is a way to simply scope these variables differently or a way to disable the sharing between sessions.
Thanks in advance!
You didn't indicate whether or not the variables need to be persisted across page round trips or whether they are just used within each page's lifecycle.
If they are not persisted across pages, then perhaps the easiest solution is to have all of your pages inherit from a based page class and then move the values from the module into the base page. This way you won't have to change any variable references, only page inheritance.
If you do want to persist the values, completing the above changes makes it much easier to implement. You can then turn the member variables on the base page into properties and embed your user specific caching and fetching in the getter and setter.
For example, instead of:
Public MyVariable As String = ""
You would have something like:
Public Property MyVariable As String
Get
Return GlobalMyVariableCache(UserNameKey)
End Get
Set (Value As String)
GlobalMyVariableCache(UserNameKey) = Value
End Set
End Property
The problem you are coming across is a very common one in web programming. A Module's members are static - meaning there is one instance of them across the entire AppDomain of your application. Every user that accesses these will get the same object - you have already learned this.
Your options are exactly what you described. You could possibly replace the public variable in your module with a property whose getter you write to access a user-specific field in a dictionary (please remember thread safety when writing this getter code).
The much easier solution would be to use the Session. Session values are stored server-side and are user specific. The only thing that get's sent client side is the session key, and if you are using .Net authentication, this is likely already getting sent.
Good luck,

ASP.NET COM+ Dispose Exception

our ASP.NET application is using COM+ to connect to Database
we have this structure:
A Base Class :
Imports System.EnterpriseServices
Public Class Base Inherits ServicedComponent
A Child Class:
Public Class Member Inherits Base
'Propreties
.
.
.
'Methods
Public Sub SetMember(ByVal SelectedQueue As String)
...
End Sub
In a Aspx page, we search for a member and set details:
Dim newMember As Member = New Member
newMember.SetMember(MemberNumber)
Session("SelectedMember") = newMember
We then dispose newMember:
If Not newMember Is Nothing Then
newMember.Dispose()
End If
but whenver we access the session we got an exception:
If Not Session("SelectedMember") Is Nothing Then
'Something
Else
'Something else
End If
the exception is :
Cannot access a disposed object. Object name: 'ServicedComponent'.
How can I dispose the object but keep my session valid?
I can see what you're doing wrong, but can't be clear on what would be right. Your logic as stated is:
Obtain object.
Store object.
Clean-up object, rendering it useless.
Retrieve object.
Use object.
Having 3 before 5 makes no sense.
If the object is quick to obtain, you should just do so on every page. (Often people over-estimate the cost of this).
If the object is slow to obtain, and it makes sense to store for a long term, then it shouldn't need to be cleaned-up. What is Dispose() actually doing here? With it obtaining and releasing resources used by members as needed.
I suspect that the first is the one to go for here, but that's mostly a guess.
I'd also be concerned when you talk about the database, does your object hold a database connection? If so, and pooling is available, then you should be releasing those connections as fast as possible, rather than holding onto them.

Aspx, global instance of class, possible bug in code structure

I am tracking down a bug in some old aspx code. The problem is that one some very rare occations (1/10.000 pageviews or so) two users are mixed up, ie. user A sees user B data.
Here is how the code is structured: We have a user class which is defined in a module like this:
Public Module MyGlobals
Public myUser As CMyUser
End Module
On the loginpage, we validate the username/password and if valid then the coorosponding userid is loaded from db, and we do:
FormsAuthentication.SetAuthCookie(userid, False)
Then we redirect to the secure area. In the secure areas MasterPage, on event Page_Init, we then have:
If Context.User.Identity.IsAuthenticated then
' Initialize the user class (user data is loaded)
MyGlobals.myUser = New CMyUser(Context.User.Identity.Name)
Else
' Redirect to loginpage
End If
Hereafter, is it safe to access the
MyGlobals.myUser
instance from every page which has the secure masterpage as masterpage, or could there be issues with this structure?
A VB.Net Module is like a static class with a private constructor and only static fields in C#.
That means, all variables declared in a module are shared across all threads. Hence every request(User) that's using this module will overwrite the old value.
I would strongly recommend to use Session to store user-sensitive data.
But i'm not sure why you want to store the Username because it's already stored when using FormsAuthentication(as you've shown yourself above).
If you really need this wrapper, you could easily achieve it even in a static context via HttpContext.Current.Session:
Module MyGlobals
Public Property myUser As CMyUser
Get
If HttpContext.Current.Session("CurrentUser") Is Nothing Then
Return Nothing
Else
Return DirectCast(HttpContext.Current.Session("CurrentUser"), CMyUser)
End If
End Get
Set(ByVal value As CMyUser)
HttpContext.Current.Session("CurrentUser") = value
End Set
End Property
End Module

ASP.NET WebForms -- Processing special query-string parameters across all pages on a site -- URL Rewriting, URL Routing, or other approaches?

Working on an ecommerce site which will be integrated with a 3rd party vendor--that vendor uses different identifiers for stores than we use internally (i.e. their store ABC123 is our 001-321).
I'm researching the best approach to inspect incoming requests for reserved query-string parameters that indicate the request is using their identifiers and map the identifiers back to our identifiers (so if the request is example.com/&theirId=ABC123 I want to transform the request to example.com/&ourId=001-321).
To do this mapping I need to inspect the provided ID, execute a lookup against the database or cache, and forward the request to the specified page--limiting the modifications to just the query-string parameters (other parameters will need to be maintained, as with the details of the HTTPHeader, etc).
So far I'm researching a few different approaches:
Implementing it in a base Page (which already does too much, but has the benefit of our Logging infrastructure and some other injected dependencies)
Implementing it in an IHttpModule
Using URL Rewriting
Using URL Routing (looks like routing isn't what I want, feel free to offer insight if you think it still fits)
Performance cost is a consideration: the actual number of times this translation will occur will be very small compared to the number of requests not requiring it--perhaps 1%.
However for another integrated site we will perform this mapping on nearly every request--would a different approach be better suited to this scenario from the previous?
This is a classic case where a HTTP module makes the most sense--you wish to dive into the URL handling on all requests. Perf-overhead-wise you shouldn't have that much of an issue presuming you can short-circuit things correctly and avoid doing DB/cache lookups where you don't need.
Configuration-wise, you should already have to solve the problem of deploying and managing your configuration, so I doubt if another custom module adds much overhead.
Code-wise, its generally better to favor composition over inheritance--you can add or remove the module as required--but having code statically included into a bloated base page class can create more challenges.
I have implemented something similar to this as a base page class for my aspx pages, but as you mentioned a module would work as well. In my opinion, if this functionality is needed across all pages I would just crate a base class only because maintaining another http-module is more of a pain because it needs to be mapped in your web config / iis. Url rewriting is cpu intensive and may not provide you the flexibility you need - again it just adds another configuration / iss dependency. I don't think either of these are going to incur much overhead as long as you implement some sort of caching.
Hope this helps...
Enjoy!
I usually create a Singleton class to hold the site's request context, and store it in the HttpContext.Current.Items(). I initialize this class in the Application_BeginRequest routine.
Imports System.Web
Public Class SiteContext
Private _viewId As Int32
Private _tab As String
Private _action As String
Private Sub New()
_viewId = -1
_tab = String.Empty
_action = String.Empty
FillContext()
End Sub
Public Shared Function Instance() As SiteContext
' gets the site specific context for the current request
If HttpContext.Current.Items("RequestContext") Is Nothing Then
HttpContext.Current.Items("RequestContext") = New SiteContext
End If
Return HttpContext.Current.Items("RequestContext")
End Function
' fill the request context with site specific items
Private Sub FillContext()
' iterate through all items passes via the querystring and save values to matching key property names
For i As Int16 = 0 To _context.Request.QueryString.Count - 1
Dim qryItem As String = _context.Request.QueryString.Keys.Item(i)
Select Case qryItem
Case "v", "view", "viewid", "vid" ' VIEW ID
If IsNumeric(_context.Request.QueryString(qryItem)) AndAlso CType(_context.Request.QueryString(qryItem), Double) < 10000 Then
_viewId = CType(_context.Request.QueryString(qryItem), Int32)
End If
Case "tab" ' TAB ID; secondary parameter to choose sub view
_tab = _context.Request.QueryString(qryItem)
Case "action" ' ACTION ID; tertiary parameter to choose sub-sub view
_action = _context.Request.QueryString(qryItem)
Case Else
End Select
Next
End Sub
Public Property ViewId() As Int32
Get
Return _viewId
End Get
Set(ByVal Value As Int32)
If Value < 1 Then
Value = 1
End If
_viewId = Value
End Set
End Property
Public Property Tab() As String
Get
Return _tab
End Get
Set(ByVal Value As String)
_tab = Value.Trim
End Set
End Property
Public Property Action() As String
Get
Return _action
End Get
Set(ByVal Value As String)
_action = Value.Trim
End Set
End Property
End Class

Resources