Question

This is a followup to the question here, where the answer seems to refer to an overly-complicated and overly-specific (EF, which I'm not using - not even using an ORM).

There has to be a more straightforward way around this common scenario than the smoke, mirrors, and sorcery hinted at in that answer.

Note: I encased "context" in parenthesis because I'm not using EF, so it is not a literal "dbcontext" that I'm talking about here.

So I got to wondering: Could I set a global variable for each session when the user is authenticated and authorized?

e.g., when the user is authenticated/authorized, I would know which database context/contents should be served up to him.

So it seems I could set a value in Global.asax.cs' Application_Start() method and then either alter the RepositoriesInstaller (implementing IWindsorInstaller) class to conditionally register different concrete Repositories based on the user and what data he should have OR place conditional code in the concrete Repository itself to use this or that database instance.

Is this feasible? Is one way (altering the RepositoriesInstaller / altering the concrete Repositories class) preferred?

Was it helpful?

Solution

Have a look at this answer which will show you how to resolve the correct repository based on a key or value.

If you want to store it with the authorized user, you need to simple serialize the data and store it on the authenticated cookie:

Create a Model to represent the logged in information:

public class AuthenticatedMember
{
    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public int SiteNumber { get; set; }
}

Do something like a login in your controller:

var authenticatedMember = MembershipManager.ValidateLogin(model.Email, model.Password);

var cookie = FormsAuthentication.GetAuthCookie(authenticatedMember.Id.ToString(), false);
var ticket = FormsAuthentication.Decrypt(cookie.Value);

var newTicket = new FormsAuthenticationTicket(ticket.Version, ticket.Name, ticket.IssueDate, ticket.Expiration, ticket.IsPersistent, authenticatedMember.ToJson(), ticket.CookiePath);

cookie.Value = FormsAuthentication.Encrypt(newTicket);
Response.Cookies.Add(cookie);

Then use a model binder to deserialize the AuthenticatedMember when you require:

public class AuthenticatedMemberModelBinder : IModelBinder
{
    #region IModelBinder Members

    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        if (bindingContext.Model != null)
        {
            throw new InvalidOperationException("Cannot update instances");
        }

        if (controllerContext.RequestContext.HttpContext.Request.IsAuthenticated)
        {
            var cookie = controllerContext
                .RequestContext
                .HttpContext
                .Request
                .Cookies[FormsAuthentication.FormsCookieName];

            if (null == cookie)
                return null;

            var decrypted = FormsAuthentication.Decrypt(cookie.Value);

            if (!string.IsNullOrEmpty(decrypted.UserData))
            {
                return JsonConvert.DeserializeObject<AuthenticatedMember>(decrypted.UserData);
            }
        }
        return null;
    }

    #endregion
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top