Monday, September 16, 2013

URL routing in ASP.NET MVC

In ASP.NET MVC, the routing is very easy. By examine the URL, its automatically find the controller and then actions.



But, to select a single controller for all kinds of URL, followings can help

           routes.MapRoute(
                "Single",
                "{page}",
                new { controller = "Single", action = "Single" }
            );
            routes.MapRoute(
                "SingleChild",
                "{page}/{child}/{*ignore}",
                new { controller = "Single", action = "Child" }
            );
            routes.MapRoute(
                null,
                "",
                defaults: new { controller = "Single", action = "Home" }
            );

Turning output caching off for authenticated users in ASP.NET MVC

While working on ASP.NET MVC 4, I was badly needed to implement caching to speed up the page loading. Caching is very easy to use and also powerful in ASP.NET MVC. But I needed to turn off the caching for admin. Let me explain why I was needed it.

In our CMS, there is an option for the admin to edit the content inline directly in the main website. The admin don't need to go to dashboard and find the content for editing. When the admin will log-in in the website, they will get this options to edit the content. If I cache the website normally, then either admin will not see the option to edit the content or end user will see the option to edit it.

In ASP.NET MVC, it can be possible to show different cache to the end user and admin using VaryByCustom parameter. But this is not the solution. The admin will not see the immediate update that he just made. Therefore I need to turn off the caching for the authenticated users only. 

In ASP.NET MVC, we used OutputCache attribute to do the caching easily. There are some properties by which you can customize the output cache. But these don't solve my problem.

To solve this I needed to create a new Cache class by extending the OutputCacheAttribute class and only override the OnResultExecuting method. OnResultExecuting method is called before the action result executes. In this methods I have checked that if aa user is authenticated then disable caching. Following is my code:

 public class MyCacheAttribute : OutputCacheAttribute
    {
        public override void OnResultExecuting(ResultExecutingContext filterContext)
        {
            var httpContext = filterContext.HttpContext;

            if (httpContext.User.Identity.IsAuthenticated)
            {
                // making cach location none means no cache
                base.Location = OutputCacheLocation.None;
            }
            else
            {
                // you can put your favorite cache location
                base.Location = OutputCacheLocation.Any;
            }

            httpContext.Response.Cache.AddValidationCallback(IgnoreAuthenticated, null);
            base.OnResultExecuting(filterContext);
        }

        private void IgnoreAuthenticated(HttpContext context, object data, ref HttpValidationStatus validationStatus)
        {
            if (context.User.Identity.IsAuthenticated)
                validationStatus = HttpValidationStatus.IgnoreThisRequest;
            else
                validationStatus = HttpValidationStatus.Valid;
        }
    }

Now to use the cache as follows
 public class PagesController 
{
      [MyCache(CacheProfile = "Cache_profile")]
      public ActionResult Index(){
           // the codes
           return View();
}