How do I replace the base MVC ActionFilter controller (or whatever)?

I am trying to improve my MVC design. On each page, I need to read the cookie and set a User object with different values ​​based on that (non-authentication related).

I am currently using all controllers that inherit from BaseController and using the User object in BaseController.

public class BaseController : Controller
{
    protected User thisUser { get; private set; }

    protected override void Initialize(System.Web.Routing.RequestContext requestContext)
    {
         // ... read cookie, set values of thisUser
    }
}

      

Is this bad design? I only like the definition User

once, but I read the answer to What are good candidates for a base controller class in ASP.NET MVC? and I'm open to redo it if there is a better way. But I definitely don't want an approach that means repeating User thisUser = new User();

on every controller, and I can't see how I can implement this without a base controller. I can't find a good example that uses ActionFilters in this way.

I'm not using the DI framework yet, but if that solves the problems. If that means passing User

as a parameter to every controller or action, I'm not sure the DRY amount is improving.

I'm sure there is something I am missing. Any help would be appreciated ...

+3


source to share


1 answer


Create an interface

interface ICustomPrincipal : IPrincipal
{
    int UserId { get; set; }
    string FirstName { get; set; }
    string LastName { get; set; }
}

      

CustomPrincipal

public class CustomPrincipal : ICustomPrincipal
{
    public IIdentity Identity { get; private set; }
    public bool IsInRole(string role) { return false; }

    public CustomPrincipal(string email)
    {
        this.Identity = new GenericIdentity(email);
    }

    public int UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

      

CustomPrincipalSerializeModel - Serializes custom information in the userdata field in the FormsAuthenticationTicket object.

public class CustomPrincipalSerializeModel
{
    public int UserId { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

      

LogIn method - setting a cookie with custom information



if (Membership.ValidateUser(viewModel.Email, viewModel.Password))
{
    var user = userRepository.Users.Where(u => u.Email == viewModel.Email).First();

    CustomPrincipalSerializeModel serializeModel = new CustomPrincipalSerializeModel();
    serializeModel.UserId = user.Id;
    serializeModel.FirstName = user.FirstName;
    serializeModel.LastName = user.LastName;

    JavaScriptSerializer serializer = new JavaScriptSerializer();

    string userData = serializer.Serialize(serializeModel);

    FormsAuthenticationTicket authTicket = new FormsAuthenticationTicket(
             1,
             viewModel.Email,
             DateTime.Now,
             DateTime.Now.AddMinutes(15),
             false,
             userData);

    string encTicket = FormsAuthentication.Encrypt(authTicket);
    HttpCookie faCookie = new HttpCookie(FormsAuthentication.FormsCookieName, encTicket);
    Response.Cookies.Add(faCookie);

    return RedirectToAction("Index", "Home");
}

      

Global.asax.cs - Reading a cookie and replacing the HttpContext.User object, this is done by overriding PostAuthenticateRequest

protected void Application_PostAuthenticateRequest(Object sender, EventArgs e)
{
    HttpCookie authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];

    if (authCookie != null)
    {
        FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(authCookie.Value);

        JavaScriptSerializer serializer = new JavaScriptSerializer();

        CustomPrincipalSerializeModel serializeModel = serializer.Deserialize<CustomPrincipalSerializeModel>(authTicket.UserData);

        CustomPrincipal newUser = new CustomPrincipal(authTicket.Name);
        newUser.UserId = serializeModel.UserId;
        newUser.FirstName = serializeModel.FirstName;
        newUser.LastName = serializeModel.LastName;

        HttpContext.Current.User = newUser;
    }
}

      

Accessing Razor Views

@((User as CustomPrincipal).Id)
@((User as CustomPrincipal).FirstName)
@((User as CustomPrincipal).LastName)

      

for a complete answer use this thread: ASP.NET MVC - Setting a Custom IIdentity or IPrincipal

+3


source







All Articles