3

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?

Jason
  • 51,583
  • 38
  • 133
  • 185

2 Answers2

3

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
  • 5,769
  • 6
  • 30
  • 40
  • be careful of issues with the currentPrincipal on the thread and the currentprincipal on the context – Lewis Jun 05 '09 at 10:09
  • 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 Jun 05 '09 at 10:10
  • 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 Jun 05 '09 at 10:11
  • [InvalidCastException: Unable to cast object of type 'System.Security.Principal.GenericPrincipal' to type myProject.CurrentUser'.] :( what am i doing wrong? – Jason Jun 05 '09 at 18:11
2

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,252
  • 12
  • 23