Recently, I had to make a crumb-trail in the web application that I am working on (ASP.NET MVC). There are multiple ways of doing this and initially I elected to do this in my controller base class (which is inherited by all my controller classes). I created a method that do the job - but this means that this method has to be called on every single action (with GET method). If a fellow developer miss to call the method, then it would mean that the data in the crumb-trail is not built properly or accurately. If there is just an interceptor that I can hook into that will run automatically every time a controller action is being called ... *sigh
Wait - there is one, ActionFilter!!
Inside the view, just get the queue from the ViewBag and display accordingly. The queue is stored temporarily in a cookie, so it will be remembered even when the browser is closed and reopen and relogin.
- public class CrumbTrailKeyValuePair<TKey, TValue>
- {
- public CrumbTrailKeyValuePair() { }
- public CrumbTrailKeyValuePair(TKey key, TValue value)
- {
- Key = key;
- Value = value;
- }
- public TKey Key { get; set; }
- public TValue Value { get; set; }
- }
- public class CrumbTrailAttribute : ActionFilterAttribute
- {
- public override void OnResultExecuting(ResultExecutingContext filterContext)
- {
- if (filterContext.HttpContext.User.Identity.IsAuthenticated)
- {
- // skip recording Account controller actions
- if (filterContext.RouteData.Values["controller"] != null &&
- filterContext.RouteData.Values["controller"].ToString() != "Account")
- {
- // put in cookies
- Queue<CrumbTrailKeyValuePair<string, string>> crumbTrailQueue =
- new Queue<CrumbTrailKeyValuePair<string, string>>();
- HttpCookie crumbTrailCookie =
- filterContext.HttpContext.Request.Cookies["CrumbTrailLinks"] ?? new HttpCookie("CrumbTrailLinks");
- // initialize serializer
- var serializer = new JavaScriptSerializer();
- // if crumbTrailCookie is not empty, retrieve value from cookie the rehydrate queue
- if (crumbTrailCookie != null && !string.IsNullOrEmpty(crumbTrailCookie.Value))
- {
- // rehydrate crumbTrailQueue with cookie value
- crumbTrailQueue =
- new Queue<CrumbTrailKeyValuePair<string, string>>
- (serializer.Deserialize<IEnumerable<CrumbTrailKeyValuePair<string, string>>>
- (HttpUtility.UrlDecode(crumbTrailCookie.Value)));
- }
- if (filterContext.HttpContext.Request.HttpMethod.ToUpper() == "GET")
- {
- // get page title
- var pageTitle = string.IsNullOrEmpty(filterContext.Controller.ViewBag.Title) ?
- "PAGE" : filterContext.Controller.ViewBag.Title;
- // get url
- string url = filterContext.HttpContext.Request.RawUrl;
- // if current page is not in both queue, then add it
- if (!crumbTrailQueue.Any(x => x.Value == url && x.Key == pageTitle))
- {
- // remove oldest menu item, keep queue length to 6
- if (crumbTrailQueue.Count >= 5)
- crumbTrailQueue.Dequeue();
- // insert new menu item into queue
- crumbTrailQueue.Enqueue(new CrumbTrailKeyValuePair<string, string>(pageTitle, url));
- }
- crumbTrailCookie.Value = serializer.Serialize(crumbTrailQueue);
- crumbTrailCookie.Expires = DateTime.Now.AddDays(365);
- crumbTrailCookie.Path = "/";
- filterContext.HttpContext.Response.Cookies.Add(crumbTrailCookie);
- }
- // put in viewbag
- if (filterContext.Result.GetType().Name == "ViewResult")
- {
- (filterContext.Result as ViewResult).ViewBag.QuickAccessQueue = crumbTrailQueue;
- }
- }
- }
- }
- }
No comments:
Post a Comment