0

Im using mvc3 that is using the asp.net membership database. I have created a table called Business that contains the UserId(from the aspnet_users table),BusinessId and BusinessName fields.

I know using Context.CurrentUser.....I can get the username etc.

I need to be able to store the BusinessId somewhere where any of my controllers can access, what is the best way to do this? I dont want to make a call back to the database everytime to get the BusinessId based on the current user

Do I create a context.session somewhere?

Any pointers would be really helpful!

Diver Dan
  • 9,953
  • 22
  • 95
  • 166

1 Answers1

0

One possibility is to use a session variable. Another one is to persist this information in the userData part of the authentication ticket which is stored in the cookie. Then you could write a custom principal and authorize attribute which will read the authentication cookie, decrypt the ticket and retrieve the information.


UPDATE:

As requested in the comments section here's an example of how the second approach could be implemented.

We start with defining a custom principal:

public class CustomPrincipal : GenericPrincipal
{
    public CustomPrincipal(IIdentity identity, string[] roles, string businessId)
        : base(identity, roles)
    {
        BusinessId = businessId;
    }
    public string BusinessId { get; private set; }
}

then a custom authorize attribute:

public class CustomAuthorize : AuthorizeAttribute
{
    protected override bool AuthorizeCore(HttpContextBase httpContext)
    {
        var isAuthorized = base.AuthorizeCore(httpContext);
        if (isAuthorized)
        {
            var cookie = httpContext.Request.Cookies[FormsAuthentication.FormsCookieName];
            var ticket = FormsAuthentication.Decrypt(cookie.Value);
            var identity = new GenericIdentity(ticket.Name);
            var principal = new CustomPrincipal(identity, null, ticket.UserData);
            httpContext.User = principal;
        }

        return isAuthorized;
    }
}

next we need to modify the login action so that the business id is included in the userData part of the authentication cookie:

[HttpPost]
public ActionResult LogOn(string username, string password)
{
    SomeUserModel user = FetchUserFromSomewhere(username, password);
    if (user == null)
    {
        // wrong username/password => redisplay login form
        return View();
    }

    var ticket = new FormsAuthenticationTicket(
        1,
        username,
        DateTime.Now,
        DateTime.Now.AddMinutes(FormsAuthentication.Timeout.TotalMinutes),
        false,
        user.BusinessId // that's where we store the business id
    );
    var encryptedTicket = FormsAuthentication.Encrypt(ticket);
    var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket)
    {
        HttpOnly = true,
        Secure = FormsAuthentication.RequireSSL
    };
    Response.AppendCookie(cookie);
    return RedirectToAction("Index", "SomeController");
}
}

And the last part is to use the custom authorize attribute on some action:

[CustomAuthorize]
public ActionResult Foo()
{
    var businessId = ((CustomPrincipal)User).BusinessId;
    ...
}

You could write a base controller and expose this custom principal as a property to avoid casting everytime you need to access the business id.

Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Thanks Darin, what is considered best practice? – Diver Dan Apr 30 '11 at 09:24
  • @Diver Dan, personally I would go with the second as I try to avoid session when possible. – Darin Dimitrov Apr 30 '11 at 09:25
  • Thanks I will do some research into creating a custom principal attribute – Diver Dan Apr 30 '11 at 09:32
  • Hi Darin, you wouldnt know of any useful blogs around this subject? the closest I have found seems to be http://stackoverflow.com/questions/4237394/asp-net-mvc-3-using-authentication however can seem to get the PostAuthenticateRequest working – Diver Dan Apr 30 '11 at 10:07
  • @Diver Dan, I've updated my post with an example. The post you have found is pretty close but personally I prefer using a custom authorize attribute instead of `PostAuthenticateRequest` because it is more ASP.NET MVCish. – Darin Dimitrov Apr 30 '11 at 10:15