Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I store a users preferences in MVC3

I have an MVC3 application and I would like to give the users the ability to set preferences that would be enabled when the user logs in.

I really don't have any idea where to start with this and would really appreciate being pointed in the right direction. I did try some changes to the membership class but now I am thinking that's probably not the best way to go about things.

like image 579
Grace Avatar asked Nov 14 '22 21:11

Grace


2 Answers

You could do it in a database (sounds like you might be using one at least with the out-of-the-box membership provider) once uniquely identifying a user. In that case, you may want to implement your own membership provider.

You have to do a little work to start implementing your own provider. If this is your only requirement, you might be able to avoid it by writing your own class that returns settings in a format of your choosing

public static class UserSettings
{
    public static string GetSettings(IPrincipal user)
    {
        if(user.Identity.IsAuthenticated)
        {
            // dip into database using user.Identity.Name property
            return "string with user settings";
            // this also assumes user.Identity.Name is uniquely able
            // to identify a user in your database!
        }

        return string.Empty;
    }
}

Or, if the information is completely trivial, maybe you could implement a cookie representation of the user settings. This, of course, comes with all the caveats of using cookies, but you could avoid storing the information in a database

Anywhere you have an HttpContext you could grab the settings value like so:

if(HttpContext.Current != null)
{
    string userSettings = HttpRequest.Current.Request.Cookies["NameOfCookie"];
}
like image 182
David Fox Avatar answered Dec 18 '22 09:12

David Fox


You can use the FormsAuthentication cookie to store your user information and avoid accessing the database all the time. That cookie is encrypted and whatever information you're storing as safe as the user session itself. The only problem with the cookies is that they have a maximum size of 4K so, if your user info is massive then you might run into a problem. When I use the cookie approach I store my user data as a JSON and then deserialize that JSON on each page request. Here is my login controller logic (I'm using SimpleMembership but the approach is the same:

 public ActionResult Login(LoginModel model, string returnUrl)
 {
     if (ModelState.IsValid && WebSecurity.Login(model.UserName, model.Password, model.RememberMe))
     {
         var authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
         if (authCookie != null)
         {
             var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
             if (authTicket != null)
             {
                 var user = _userLogic.GetItem(model.UserName);
                 if (user != null && user.IsActive)
                 {
                     var newAuthTicket = new FormsAuthenticationTicket(authTicket.Version, authTicket.Name, authTicket.IssueDate, authTicket.Expiration, authTicket.IsPersistent, JsonConvert.SerializeObject(user));
                     var newCookie = new HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(newAuthTicket))
                     {
                         Expires = authCookie.Expires
                     };
                     Response.Cookies.Add(newCookie);
                     return RedirectToLocal(returnUrl);
                 }
                 WebSecurity.Logout();
                 ModelState.AddModelError("UserName", "This account has been deactivated.");
                 return View(model);
             }
         }
     }
     // If we got this far, something failed, redisplay form
     ModelState.AddModelError("", "The user name or password provided is incorrect.");
     return View(model);
 }

Notice the newAuthTicket creation and how user instance is passed to it as a JSON. After that all I have to do is desirialize this user object in my base controller's OnAuthorization method:

    protected override void OnAuthorization(AuthorizationContext filterContext)
    {
        var authCookie = Request.Cookies[FormsAuthentication.FormsCookieName];
        if (authCookie != null)
        {
            var authTicket = FormsAuthentication.Decrypt(authCookie.Value);
            if (authTicket != null)
            {
                var principal = new CustomPrincipal(HttpContext.User.Identity)
                {
                    CurrentUserInfo = JsonConvert.DeserializeObject<User>(authTicket.UserData)
                };
                HttpContext.User = principal;
                AppUser = principal.CurrentUserInfo;
                ViewBag.AppUser = AppUser;
            }
        }
        base.OnAuthorization(filterContext);
    }
like image 40
Marko Avatar answered Dec 18 '22 09:12

Marko