I'm developing a multi-app framework (like Wordpress) that can host multiple websites in a single application.
During application start event I initialize a couple of static classes wich contains global app settings, local app setting (for each of the websites) and local authorization stores (roles, pages, task for each app).
Now to make my life easier when coding I'm buildin a sort of "wrapper" for local application settings so that I don't have to pass each time the actual ApplicationId for the context (based on site url and mapped to a db retrieved GUID).
My concern (since I'm a complete newbie with asp.net) is if concurrent requests could pose issues accessing a static class but using a value from current context.
This is the code.
Public NotInheritable Class AppSettings
Private Shared pErrorLogTimeFilterSecond As Dictionary(Of Guid, Integer)
' ApplicationId is populated in the context on each application Begin_Request event
Private Shared ReadOnly pApplicationId As Guid = DirectCast(HttpContext.Current.Items("ApplicationId"), Guid)
Public Shared ReadOnly Property ApplicationId As Guid
Get
Return pApplicationId
End Get
End Property
Public Shared ReadOnly Property ErrorLogTimeFilterSeconds As Integer
Get
Return pErrorLogTimeFilterSecond(ApplicationId)
End Get
End Property
...
In your code there is only a single ApplicationId property that everyone will share. So when one call initialises AppSettings, the ApplicationID will be there data, but if while processing that request another call initialises AppSettings too then the ApplicationID
will be overwritten and when your first call queries the property they will get the data of the second call.
Are you saying this approach would not be thread safe so that for example:
- First call retrieves the AppSettings.ApplicationId and it's correct since it's taken from its context
- A concurrent second call retrieves AppSettings.ApplicationId and it's correct since it's taken from its context
- In the same context first call retrieves AppSettings.ErrorLogTimeFilterSeconds and it will be WRONG because pApplicationId private field has been overwritten by the second call? Wouldn't at this time pApplicationId be overwritten again from the first call?
If that's right could a refactoring technique look similar to this:
Public Shared ReadOnly Property ErrorLogTimeFilterSeconds As Integer
Get
Return pErrorLogTimeFilterSecond(DirectCast(HttpContext.Current.Items("ApplicationId"), Guid))
End Get
End Property
In this case I guess it will always be the right context?
Private Shared ReadOnly pApplicationId As Guid = DirectCast(HttpContext.Current.Items("ApplicationId"), Guid)
is only run once, the first time it is accessed, however once set up it is then global across all callers.
Your refactor should work as it means that rather than using a shared variable, the class returns something based on the current context which will be different for each caller.
Otherwise I should copy current application settings for each request from the global repository to the context on each begin_request
I think this solution it's better than copying
Just another doubt... will this work (the property ApplicationId will be accessed and re-populated with the correct context) or is the same as previous using private field wich is initialized just once?
Public Shared ReadOnly Property ApplicationId As Guid
Get
Return DirectCast(HttpContext.Current.Items("ApplicationId"), Guid)
End Get
End Property
Public Shared ReadOnly Property TasksInRoles As Dictionary(Of Integer, List(Of Integer))
Get
Return appsAuthStore(ApplicationId).TasksInRoles
End Get
End Property
Otherwise I have to
Public Shared ReadOnly Property ApplicationId As Guid
Get
Return DirectCast(HttpContext.Current.Items("ApplicationId"), Guid)
End Get
End Property
Public Shared ReadOnly Property TasksInRoles As Dictionary(Of Integer, List(Of Integer))
Get
Return appsAuthStore(DirectCast(HttpContext.Current.Items("ApplicationId"), Guid)).TasksInRoles
End Get
End Property
manight
Member
59 Points
60 Posts
Using HttpContext.Current.Items in a static class
Dec 20, 2012 01:06 PM|LINK
I'm developing a multi-app framework (like Wordpress) that can host multiple websites in a single application.
During application start event I initialize a couple of static classes wich contains global app settings, local app setting (for each of the websites) and local authorization stores (roles, pages, task for each app).
Now to make my life easier when coding I'm buildin a sort of "wrapper" for local application settings so that I don't have to pass each time the actual ApplicationId for the context (based on site url and mapped to a db retrieved GUID).
My concern (since I'm a complete newbie with asp.net) is if concurrent requests could pose issues accessing a static class but using a value from current context.
This is the code.
Public NotInheritable Class AppSettings Private Shared pErrorLogTimeFilterSecond As Dictionary(Of Guid, Integer) ' ApplicationId is populated in the context on each application Begin_Request event Private Shared ReadOnly pApplicationId As Guid = DirectCast(HttpContext.Current.Items("ApplicationId"), Guid) Public Shared ReadOnly Property ApplicationId As Guid Get Return pApplicationId End Get End Property Public Shared ReadOnly Property ErrorLogTimeFilterSeconds As Integer Get Return pErrorLogTimeFilterSecond(ApplicationId) End Get End Property ...AidyF
Star
9246 Points
1576 Posts
Re: Using HttpContext.Current.Items in a static class
Dec 20, 2012 01:26 PM|LINK
In your code there is only a single ApplicationId property that everyone will share. So when one call initialises AppSettings, the ApplicationID will be there data, but if while processing that request another call initialises AppSettings too then the ApplicationID will be overwritten and when your first call queries the property they will get the data of the second call.
manight
Member
59 Points
60 Posts
Re: Using HttpContext.Current.Items in a static class
Dec 20, 2012 01:55 PM|LINK
Hi AidyF, thanks.
Are you saying this approach would not be thread safe so that for example:
- First call retrieves the AppSettings.ApplicationId and it's correct since it's taken from its context
- A concurrent second call retrieves AppSettings.ApplicationId and it's correct since it's taken from its context
- In the same context first call retrieves AppSettings.ErrorLogTimeFilterSeconds and it will be WRONG because pApplicationId private field has been overwritten by the second call? Wouldn't at this time pApplicationId be overwritten again from the first call?
If that's right could a refactoring technique look similar to this:
Public Shared ReadOnly Property ErrorLogTimeFilterSeconds As Integer Get Return pErrorLogTimeFilterSecond(DirectCast(HttpContext.Current.Items("ApplicationId"), Guid)) End Get End PropertyIn this case I guess it will always be the right context?
AidyF
Star
9246 Points
1576 Posts
Re: Using HttpContext.Current.Items in a static class
Dec 20, 2012 02:06 PM|LINK
This line;
Private Shared ReadOnly pApplicationId As Guid = DirectCast(HttpContext.Current.Items("ApplicationId"), Guid)is only run once, the first time it is accessed, however once set up it is then global across all callers.
Your refactor should work as it means that rather than using a shared variable, the class returns something based on the current context which will be different for each caller.
manight
Member
59 Points
60 Posts
Re: Using HttpContext.Current.Items in a static class
Dec 20, 2012 02:27 PM|LINK
Ok... going down this road then! Thanks
Otherwise I should copy current application settings for each request from the global repository to the context on each begin_request
I think this solution it's better than copying
manight
Member
59 Points
60 Posts
Re: Using HttpContext.Current.Items in a static class
Dec 20, 2012 04:28 PM|LINK
Just another doubt... will this work (the property ApplicationId will be accessed and re-populated with the correct context) or is the same as previous using private field wich is initialized just once?
Public Shared ReadOnly Property ApplicationId As Guid Get Return DirectCast(HttpContext.Current.Items("ApplicationId"), Guid) End Get End Property Public Shared ReadOnly Property TasksInRoles As Dictionary(Of Integer, List(Of Integer)) Get Return appsAuthStore(ApplicationId).TasksInRoles End Get End PropertyOtherwise I have to
Public Shared ReadOnly Property ApplicationId As Guid Get Return DirectCast(HttpContext.Current.Items("ApplicationId"), Guid) End Get End Property Public Shared ReadOnly Property TasksInRoles As Dictionary(Of Integer, List(Of Integer)) Get Return appsAuthStore(DirectCast(HttpContext.Current.Items("ApplicationId"), Guid)).TasksInRoles End Get End Propertymanight
Member
59 Points
60 Posts
Re: Using HttpContext.Current.Items in a static class
Dec 20, 2012 04:56 PM|LINK
I just realized it's a dumb question since ApplicationId is really never "set" it just returns from current context.
(just in case someone else is dumb as me the first example is ok!) :D