Viktor
Viktor

Reputation: 101

Where can I store email and userId in my ASP.NET MVC application so I don't have to retrieve it with every request?

I'm writing an ASP.NET MVC application and I'm using forms authentication with the default IPrincipal, IIDentity, etc.

In my authentication ticket I'm storing the username in the name parameter.

However, I'm running into instances where on every request my master layout needs access to not only the username, but also the email and userid of the user.

I need the email so I can load a gravitar icon for the user, the username so I can have a friendly display name in the top bar, and the userid so I can define certain links specific to that userid (ie, /users/edit/2332).

What is the cleanest way to store not just the username but also the userid and email?

Custom Principal/Identity objects? Cache? Session? Some other way?

Upvotes: 2

Views: 2364

Answers (3)

ten5peed
ten5peed

Reputation: 15890

Use a custom IPrincipal object with your own cookie management.

I would suggest serializing the custom IPrinicipal object to JSON and setting your cookie.UserData to the serialized string. That was it's easy to deserialize when the cookie comes back in.

EDIT: Example of a custom IPrincipal object and authentication cookie management

The IPrincipal object (note I'm using Json.NET for serialization)

public class SimplePrincipal : IPrincipal
{
    private IIdentity _identity;

    [JsonIgnore]
    public IIdentity Identity
    {
        get { return _identity ?? (_identity = new GenericIdentity(Name)); }
    }

    public string Name { get; set; }
    public int WebUserId { get; set; }
    public string Email { get; set; }
    public long FacebookUserId { get; set; }
    public IEnumerable<string> Roles { get; set; }

    public bool IsInRole(string role)
    {
        return Roles.Contains(role);
    }

    /// <summary>
    /// Get's a JSON serialized string of a SimplePrincipal object
    /// </summary>
    public static string GetCookieUserData(SimplePrincipal principal)
    {
        return JsonConvert.SerializeObject(principal);
    }

    /// <summary>
    /// Creates a SimplePrincipal object using a JSON string from the asp.net auth cookie
    /// </summary>
    public static SimplePrincipal CreatePrincipalFromCookieData(string userData)
    {
        return JsonConvert.DeserializeObject<SimplePrincipal>(userData);
    }
}

Login Method

private void LoginUser(SimplePrincipal principal, bool isPersistent)
{
    var userData = SimplePrincipal.GetCookieUserData(principal);

    var authCookie = FormsAuthService.GetAuthCookie(principal.Name, userData, isPersistent);

    Response.Cookies.Add(authCookie);
}

Authentication Module

public class AuthModule : IHttpModule
{
    public void Init(HttpApplication context)
    {
        context.AuthenticateRequest += Application_AuthenticateRequest;
    }

    private void Application_AuthenticateRequest(Object source, EventArgs e)
    {
        var application = (HttpApplication)source;
        var context = application.Context;

        // Get the authentication cookie
        string cookieName = FormsAuthentication.FormsCookieName;
        HttpCookie authCookie = context.Request.Cookies[cookieName];
        if (authCookie == null)
            return;

        var authTicket = FormsAuthentication.Decrypt(authCookie.Value);

        context.User = SimplePrincipal.CreatePrincipalFromCookieData(authTicket.UserData);
    }

    public void Dispose()
    {
        //Don't do anything
    }
}

After all this is wired up correctly, you can simply get the object something like:

var principal = HttpContext.Current.User as SimplePrincipal

Upvotes: 6

Mrchief
Mrchief

Reputation: 76218

Use Session if you want to keep it alive for the session (also the most straight forward approach). Use TempData if you want to persist it between single requests (or until it is read out).

You can also use querystring or URL params but in this case, I wouldn't suggest it.

Do not use cache as that is shared across all users of the site.

Ideally though, it should be a Custom Identity object

Upvotes: 0

Deepansh Gupta
Deepansh Gupta

Reputation: 593

I would suggest using Session object for storing this kind of information.

Upvotes: 0

Related Questions