Remembering a previous visitor

If you are the sort of developer that doesn't tend to use the profiles and membership facilities (for whatever reason...) provided by the .NET framework, then odds are that you will be making your registration process and logging-in facilities. Part of this is the ability to drop a cookie and remember the users when they come and go from your site. There are many approaches to this, some better than others. You could drop an encrypted cookie on the user's computer with the user's ID in it and, upon re-entering the site, you simply log them in and allow them to exist in the system, as if they hadn't left (as is done with Gmail). Another approach is to store their username and the like in a cookie and let the user think that you have remembered them. Then, when the user attempts to take an action that really requires them to identify themselves, you can prompt them to log in again (as LinkedIn appears to do).

How to do it...

  1. Start by creating a new default ASP.NET MVC 2 application.
  2. As this recipe is all about the cookie, we will create a helper class for working with cookies first. Create a CookieWrapper class in the Models folder. This class will handle getting, setting, and destroying cookies for us. More than that, we will expose properties, of this class that will give us the data in a strongly typed format, so that we don't have to worry about converting strings all over our application.

    Models/CookieWrapper.cs:

    public class CookieWrapper {
    private void SetCookie(string key, string value, bool thisSessionOnly) {
    HttpCookie cookie = new HttpCookie(key, value);
    if(!thisSessionOnly)
    cookie.Expires = DateTime.Now.AddMonths(1);
    HttpContext.Current.Response.Cookies.Add(cookie);
    }
    private string GetCookie(string key) {
    if (HttpContext.Current.Request.Cookies[key] != null)
    return HttpContext.Current.Request.Cookies[key].Value;
    return String.Empty;
    }
    private void RemoveCookie(string key) {
    HttpContext.Current.Response.Cookies.Remove(key);
    }
    }
    
  3. With the helper functions in place, we can now add two properties for the things that we are interested in remembering. We will have an AccountID that will return a Guid and we will have a Username property that will return the user's username.

    Models/CookieWrapper.cs:

    public class CookieWrapper {
    private const string c_accountId = "AccountId";
    private const string c_username = "Username";
    public Guid AccountID {
    get {
    string value = GetCookie(c_accountId);
    if (!String.IsNullOrEmpty(value))
    return new Guid(value);
    return Guid.Empty;
    }
    set {
    if (value == Guid.Empty)
    RemoveCookie(c_accountId);
    else
    SetCookie(c_accountId, value.ToString(), false);
    }
    }
    public string Username {
    get { return GetCookie(c_username); }
    set {
    if (String.IsNullOrEmpty(value))
    RemoveCookie(c_username);
    else
    SetCookie(c_username, value, false);
    }
    }
    ...
    }
    
  4. That is technically all we need for our cookie wrapper to work. Now we can add some logic to our application to demonstrate how this works. We will work in the Home/Index view for our display purposes. But we will also create a new action called CookieAction in HomeController.cs, which will handle a handful of operations for setting and getting our data out of cookies. These operations will be triggered by some links that we will add to the home page of our application.

    Controllers/HomeController.cs:

    public ActionResult CookieAction(string id) {
    var cookieJar = new CookieWrapper();
    switch(id) {
    case "SetAccountId":
    cookieJar.AccountID = Guid.NewGuid();
    break;
    case "SetUsername":
    cookieJar.Username = "asiemer";
    break;
    case "RemoveAccountId":
    cookieJar.AccountID = Guid.Empty;
    break;
    case "RemoveUsername":
    cookieJar.Username = String.Empty;
    break;
    }
    return RedirectToAction("Index");
    }
    
  5. In order for us to get our data to the home page, we need to set the Username and AccountID into the ViewData for our home page in the Index action of the home controller.

    Controllers/HomeController.cs:

    public ActionResult Index() {
    ViewData["Message"] = "Welcome to ASP.NET MVC!";
    var cookieJar = new CookieWrapper();
    ViewData["AccountId"] = cookieJar.AccountID;
    ViewData["Username"] = cookieJar.Username;
    return View();
    }
    
  6. The only thing left at this point is to create the links that trigger the values to be retrieved or destroyed, as well as to display the current values of the cookies. Make the following changes to ViewsHomeIndex.aspx:

    Views/Home/Index.aspx:

    <asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <h2><%: ViewData["Message"] %></h2>
    <p>
    To learn more about ASP.NET MVC visit
    <a href="http://asp.net/mvc" title="ASP.NET MVC Website"> http://asp.net/mvc</a>.
    </p>
    <p>
    <%: Html.ActionLink("Set AccountId cookie", "CookieAction", new { @id="SetAccountId"}) %>
    <br />
    <%: Html.ActionLink("Remove AccountId cookie", "CookieAction", new { @id="RemoveAccountId"}) %>
    </p>
    <p>
    <%: Html.ActionLink("Set Username cookie", "CookieAction", new { @id = "SetUsername" })%>
    <br />
    <%: Html.ActionLink("Remove Username cookie", "CookieAction", new { @id = "RemoveUsername" })%>
    </p>
    <fieldset>
    <legend>Cookie Jar</legend>
    Username: <%: ViewData["Username"] %>
    <br />
    AccountId: <%: ViewData["AccountId"] %>
    </fieldset>
    </asp:Content>
    
  7. Now you can run the application. Clicking on the links to set and destroy the data should write the contents to the cookies or remove the values all together. Because we opted to persist the cookies in the CookieWrapper, these cookies will by default be set for a month. Each time you write the cookie, this date will be updated. When closing the browser window and then opening it again, you should see that the state of your cookies have been "remembered".
    How to do it...

How it works...

As with our session wrapper in the previous recipe, we have opted to wrap the framework's concept of a cookie, which is exposed by HttpContext. This gives us a couple of benefits. First and foremost, all of our dealings with the concept of a cookie happen in one placeā€”helping to keep our code DRY. Also, it limits the exposure of magic strings that working with cookies often presents in the cookie's dependency on strings for keys. This makes the code that uses our cookie wrapper less fragile and more easily refactorable. All of these things then lead up to one more key strength in wrapping dependencies like this, in that we can easily swap out this implementation for something else for testing purposes or otherwise using an Inversion of Control container, such as StructureMap.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset