views:

1033

answers:

2

I would like to extend the System.Web.HttpContext.User object (ASP.NET/VB.NET) so that it contains other fields besides just Name. I understand I can create an object that inherits the System.Security.Principal.GenericPrincipal class, but how do I store that in the Current.User object in a usable fashion. ie, I can do something like Current.User.UserID.

So far to achieve this I've created a kludgy workaround by using | delimited strings in the User.Name property and then splitting them, but it's getting kind of ridiculous.

Any suggestions?

Thanks!

EDIT: I have tried the following to no avail:

Imports System.Security.Principal
Public Class CurrentUser : Inherits GenericPrincipal
Private _totalpoints As Integer
Private _sentencecount As Integer
Private _probationuntil As DateTime
Public ReadOnly Property TotalPoints() As Integer
 Get
  Return _totalpoints
 End Get
End Property
Public ReadOnly Property SentenceCount() As Integer
 Get
  Return _sentencecount
 End Get
End Property
Public ReadOnly Property ProbationUntil() As DateTime
 Get
  Return _probationuntil
 End Get
End Property
Public Sub New(ByVal principle As IIdentity, ByVal roles() As String, _
ByVal points As Integer, ByVal sentences As Integer, ByVal probationTil As DateTime)
 MyBase.New(principle, roles)
 _totalpoints = points
 _sentencecount = sentences
 _probationuntil = FixDBNull(probationTil)
End Sub
End Class

setting the object in my Global.asax Application_AuthenticateRequest function like so:

HttpContext.Current.User = New CurrentUser(User, userRoles, _
 points, sentenceCount, probationUntil)

with a direct cast wherever the object is needed like so:

Dim thisUser As CurrentUser = DirectCast(Current.User, CurrentUser)

i also tried CType and it didn't work... my error is

[InvalidCastException: Unable to cast object of type 'System.Security.Principal.GenericPrincipal' to type 'myProject.CurrentUser'.]

i'm losing my mind here ... :( thanks guys...

anyone?

+1  A: 

Hi Jason,

Would this approach work for you? It looks a little involved but it really doesn't take too long to setup:

  1. Create a 'base' class of your own, and have your pages inherit from that. For example, create a base class called 'BasePage' which inherits from System.Web.UI.Page.

  2. Have your ASP.net pages inherit from your new BasePage class.

  3. In the BasePage class, you can have a public property which contains the extra fields you want to store for your user (eg. BasePage.FirstName, BasePage.LastName). Better still, create a User object containing the extra fields, and expose that via BasePage, eg. "BasePage.Customer". This keeps things tidy if you plan to extend BasePage later.

  4. You can then override the OnInit() of the base class to check for HTTPContext.Current.User.Name property, and fetch the necessary info from your DB to initialise your custom properties.

You can modify the code so that it won't need to hit the database each time the page is refreshed by using ControlState to check whether the custom fields have values before populating them again from the database.

Hope this helps...

Richard.

Richard
+1  A: 

You can create your own Principal class with the required properties, that inherits from a Generic Principal, and then set the User property of your Current Context to be the a user of that type.

The example below is for ASP.Net MVC but a similar approach could be used with webforms.

You can do this in the PostAuthenticateRequest after a user is authenticated (in the Global.asax)

private void MvcApplication_PostAuthenticateRequest(object sender, EventArgs e)
        {
     SomePrincipal newUser = new SomePrincipal(User.Identity, tmpRoles);

                senderRef.Context.User = newUser;
                System.Threading.Thread.CurrentPrincipal = newUser;
}

You could then add a property or method in a base class of your page (or controller) for example that to wrap and type the Context.User principal to your Principal type and make sure you call it rather than calling the one on the HttpContext.

There are probably other solutions too!

Lewis
be careful of issues with the currentPrincipal on the thread and the currentprincipal on the context
Lewis
I'd be careful associating the user to the threads principal, http contexts can span multiple threads so it is best advised to set the httpcontexts principal instead.
meandmycode
Hah, beaten to it ;)
meandmycode
So could i do something like Class MyUser : Inherits GenericPrincipal and then set the Current.User = New MyUser... then when i reference it do something like CType(Current.User, MyUser)?
Jason
yes Jason, that should work.
Lewis
[InvalidCastException: Unable to cast object of type 'System.Security.Principal.GenericPrincipal' to type myProject.CurrentUser'.]:( what am i doing wrong?
Jason