Dziś na temat korzystania z jQuery i ciasteczek. Jako scenariusz przyjmijmy proste zliczenie kliknięć, gdzie licznik przechowujemy jako wartość ciastka.

W tym celu tworzymy aplikację ASP.NET MVC wraz z testowym kontrolerem i dwoma widokami – Indeks, który jest widokiem bazowym i Modify, który zwraca kawałek html’a z zawartością ciastka.

Kotroler inicjujemy w następujący sposób:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.Linq;
  4 using System.Web;
  5 using System.Web.Mvc;
  6
  7 namespace CookieAndJQuery.Controllers
  8 {
  9     [HandleError]
10     public class TestsController : Controller
11     {
12         private static string CookieName = “TestCookie”;
13
14         public ActionResult Index()
15         {
16             return View();
17         }
18
19         public ActionResult Modify()
20         {
21             HttpCookie cookie = Request.Cookies[CookieName];
22             if (cookie == null)
23             {
24                 cookie = new HttpCookie(CookieName, “0”);
25                 cookie.Expires = DateTime.MaxValue;
26             }
27
28             int v = int.Parse(cookie.Value);
29             cookie.Value = (++v).ToString();
30             Response.Cookies.Add(cookie);
31             ViewData[“itemValue”]= cookie.Value;
32             return View();
33         }
34     }
35 }

Indeks ma za zadanie po kliknięciu przycisku wywołać akcję Modify w kontrolerze TestsController a następnie wstrzyknąć jej wynik do diva o id=”resultContainer”

  1 <%@ Page Language=“C#” Inherits=“System.Web.Mvc.ViewPage” %>
  2 <html>
  3 <head runat=“server”>
  4     <title>Index</title>
  5     <script src=“Scripts/jquery-1.4.1.min.js” type=“text/javascript”></script>
  6 </head>
  7 <body>
  8     <div>
  9         <input type=“button” id=“btnTestCookies” value=“ClickMe” />
10         <div id=“resultContainer”></div>
11     </div>
12     <script type=“text/javascript”>
13         $(“#btnTestCookies”).click(function () {
14             $.ajax(
15                 {
16                     url: “/Tests/Modify”,
17                     success: function (data) {
18                         $(“#resultContainer”).html(data);
19                     },
20                     cache: false,
21                     dataType: “html”
22                 }
23             );
24         });
25     </script>
26 </body>
27 </html>

 

Dla pełnego obrazu poniżej widnieje zawartość widoku Modify:

  1 <%@ Page Language=“C#” Inherits=“System.Web.Mvc.ViewPage” Buffer=“false” %>
  2 <div>
  3     <%= ViewData[“itemValue”] %>
  4 </div>

Skoro mamy już bazę do doświadczeń pora przejść do sedna problemu, a mianowiscie do obsługi ciastek. Jak zapewne zauważyliście kontroler w linii 25 ustawia czas wygaśnięcia ciastka na DateTime.MaxValue, czyli ciastko nigdy nie wygaśnie. Na pierwszy rzut oka nie widać problemu: wywołujemy akcję, akcja zmienia wartość ciastka, ciastko wraca do przeglądarki, klikamy ponownie, wartość wzrasta – super! Jednakże spójżmy jak faktycznie wygląda ciastko, które otrzymujemy:

Pierwsze wywołanie strony – tworzymy ciastko

Kolejne wywołanie strony – niestety jak widać poniżej czas wygaśnięcia ciastka przypadnie na koniec sesji:

Przez to po zamknięciu i ponownym uruchomieniu przeglądarki ciastko zostanie usuniete a tym samym licznik zostanie zresetowany…

Przyjrzyjmy się jak wygląda request i response. Korzystając z Fiddlera można podejrzeć treść nagłówka Cookies, w którym widać wszystko jak na dłoni:

Odpowiedź po pierwszym wywołaniu (ustawiamy ciastko)

Request przy kojelnych kliknięciach przycisku – jak widać brak przy żądaniu informacji o ekspiracji ciastka, co skuktuje opisanym zachowaniem.

Jak to ominąć? W przypadku, który miałem jako zadanie postanowiłem przy każdym takim wywołaniu ustawiać czas życia ciastka na DateTime.MaxValue, dzięki  czemu po ponownym uruchomieniu przeglądarki ciastko nadal tam jest…

  1 public ActionResult Modify()
  2 {
  3     HttpCookie cookie = Request.Cookies[CookieName];
  4     if (cookie == null)
  5     {
  6         cookie = new HttpCookie(CookieName, “0”);
  7         cookie.Expires = DateTime.MaxValue;
  8     }
  9
10     cookie.Expires = DateTime.MaxValue;
11     int v = int.Parse(cookie.Value);
12     cookie.Value = (++v).ToString();
13     Response.Cookies.Add(cookie);
14     ViewData[“itemValue”] = cookie.Value;
15     return View();
16 }

W wyniku tej modyfikacji informacja o ciastkach znajdująca się w odpowiedzi wygląda następująco

dzięki czemu przy kolejnym uruchomieniu przeglądarki ciastko nadal tam będzie gotowe do użycia :)