Monday 16 March 2015

Exception Handling in MVC

No matter how proficiently you developed your application there are chances that your code may not work as expected and will generate an error at runtime. Users may enter some invalid data, mathematical calculations can go wrong, some network level fault may cause errors and more. That is why it is always a good idea to implement a robust error handling mechanism in your web application. To that end ASP.NET MVC offers several techniques that help you build such an error handling mechanism. This article discusses them with examples.

Exception Handling Techniques for ASP.NET MVC

Before we get into the actual error handling techniques offered by ASP.NET MVC, let's quickly enumerate them here:
  • try...catch
  • Overriding OnException method
  • Using the [HandleError] attribute on actions and controllers
  • Handling Application_Error event (Global Error Handling in Mvc)

Using the Try...Catch Statement
The simplestwayis to use the traditional .NET exception handling style i.e. try and catch block. Now when exception happens catch block gets executed and it redirects to the error view.

        public ActionResult SomeError()
        {
            try
            {
                return View();
            }
            catch (Exception ex)
            { return View("Error"); }
        }

Error.cshtml :

@model System.Web.Mvc.HandleErrorInfo

@{
    ViewBag.Title = "Error";
}

<hgroup class="title">
    <h1 class="error">Error.</h1>
    <h2 class="error">An error occurred while processing your request.</h2>
</hgroup>

Limitation:
Problem with the above approach is we cannot reuse the exception handling logic across multiple action methods.

Overriding OnException Method
In this method we can override the “OnException” event of the controller and set the “Result” to the view name. This view gets invoked when error occurs in this controller. In the below code you can see we have set the “Result” to a view named as “Error”.
We have also set the exception so that it can be displayed inside the view.

protected override void OnException(ExceptionContext filterContext)
        {
            Exception ex = filterContext.Exception;
            filterContext.ExceptionHandled = true;

            var model = new HandleErrorInfo(filterContext.Exception, "Controller", "Action");

            filterContext.Result = new ViewResult()
            {
                ViewName = "Error",
                ViewData = new ViewDataDictionary(model)
            };

        }

To display the above error in view we can use the below code in Index.cshtml file:-

@Model.Exception;

Advantage
Now we can share error handling logic across all the actions in a controller

Limitation:
Problem with the above approach is we cannot reuse the exception handling logic across multiple controllers. That where global error handling comes to picture.

Using HandleError Attribute

The other way of handling error is my using “HandleError” attribute. Implementing “HandleError” attribute is a two-step process:-
Step 1 :- We need to first decorate the action method with “HandleError” attribute as shown in the below code.
    public class HomeController : Controller
        {
            [HandleError()]
            public ActionResult SomeError()
            {
                throw new Exception("test");
            }
        }
Step 2:- In the “Web.config” file you need to add the “customErrors” tag and point to the “Error” view as shown in the below “Web.config” code snippet.

<system.web>
<customErrors defaultRedirect="Error.cshtml" mode="On">
</customErrors>
</system.web>

In case you want different error views for different exception types you can decorate action method with multiple “HandleError” attribute point to multiple views as per exception types.
   public class HomeController : Controller
        {
            [HandleError(ExceptionType = typeof(ArithmeticException), View = "Arthimetic")]
            [HandleError(ExceptionType = typeof(NotImplementedException), View = "Error1")]
            public ActionResult SomeError()
            {

            }
        }

Global Error Handling in Mvc

The last exception handling technique discussed here is the Application_Error event. If you ever worked with ASP.NET Web Forms chances are you already know about this event. The Application_Error event is raised whenever  there is any unhandled exception in the application. That means an exception is not handled by any of the other techniques discussed earlier, it eventually gets bubbled up to the Application_Error event. Inside this event handler you can do tasks such as error logging and take some alternate path of execution. The following code shows how Application_Error can be added to Global.asax:

       protected void Application_Error()
        {
            Server.ClearError();
            Response.Redirect("/home/error");
        }

The Application_Error event handler calls Server.ClearError() so as to convey to ASP.NET that the exception has been handled and that there is no longer an exception in the application. This way if you have set a custom error page in the web.config, it won't be displayed. Then the code redirects the user to /home/error so that the Error view is displayed in the browser.

Summary

Error handling is an important consideration in any web application. ASP.NET MVC offers several error handling techniques in addition to try...catch that you can use. They include - overriding OnException() method, [HandleError] attribute, HandleErrorAttribute as a global filter and Application_Error event. Which of these techniques to use depends on the granularity of exception handling you need in an application.
Continue Reading →

Sunday 15 March 2015

Caching in ASP.NET MVC

Introduction
In this article we will see how we can implement caching in an ASP.NET MVC application.

Background
As ASP.NET web developers, we are mostly involved in developing web pages that are dynamic, i.e. contents coming from databases, Server directories, XML files or getting pulled from some other websites. Caching means to store something in memory that is being used frequently to provide better performance.

Why should we even care about caching. Let us imagine a scenario when the contents of a web page are being pulled from a database. The user asks for contents depending on some criteria. Now if the database is getting changed very frequently that even between two requests of same user, we anticipate database change, then we can in no way cache the data that the user is requesting. But if the database is not getting changed that frequently, we can have some caching in place so that if the user is requesting the same data very frequently, we don't hit the database every time (since we know contents are not changed).
The two keys terms here are frequency and criteria. Frequency is the number of times we are anticipating the user requests for a particular page and criteria is what governs the uniqueness of result that is being displayed on the page.
Frequency is important because we need to figure out the interval in which database is changing and compare it with the frequency of user requests so that we can have caching in place and also make sure that user is not viewing outdated data.
Criteria is important because we need to make sure that we have caching implemented for the page on every unique criteria. It should not be the case that user is requesting contents based on criteria01 and we are showing him the cached results of criteria00 (cached earlier for him).
So with all this theory in mind, let's go ahead and see how we can implement caching in ASP.NET MVC.

Types of Caching
There are two types of caching available in ASP.NET:
  • Page Output Caching
  • Application Caching
Page Output Caching
Page output caching refer to the ability of the web server to cache a certain webpage after user request in its memory so that further requests for the same page will check for the cached page's validity and will not result in resource usage (DB access or file access) and the page will be returned to user from cache.
Let us develop a small application that will demonstrate how we can implement page output caching in ASP.NET MVC. Lets implement a simple view that will show the current time to the user. The Controller code is simply returning the view.

    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }
    }  

In my view, I am showing the current time to the user.

Time is @DateTime.Now.ToString()

If we run this application now, it will show me the current date and time. If we refresh it, the time also gets updated(since there is no caching implemented right now).


Now lets say that this page should be cached for 30 seconds i.e. the time string should not change for 30 seconds. We can achieve this by adorning the action method with the OutputCache attribute. We will pass 2 values in the attribute, First is the Duration of cache and second property VaryByParamVaryByParam="none" specifies that caching doesn't depend on anything.

    public class HomeController : Controller
    {
        [OutputCache(Duration = 30, VaryByParam = "none")]
        public ActionResult Index()
        {
            return View();
        }
    } 

Now if we run the page and refresh it, the time will not change for 30 seconds.

In the above example, we have specified VaryByParam="none". Doing so can lead to a situation where user might see stale data. So if we want to invalidate the cache based on some user selection in screen, then we can specify the VaryByParam's value. So If I want to cache different values for page requests having different query string, I can specify the varyByParam value as the name of that query string.(or any HTML element I want to use).

    public class HomeController : Controller
    {
        [OutputCache(Duration = 30, VaryByParam = "none")]
        public ActionResult Index()
        {
            return View();
        }

        [OutputCache(Duration = 30, VaryByParam = "id")]
        public ActionResult About()
        {
            return View();
        }
     }

So now if I run the application and navigate to About, I will see a cached version for each value of "id" query string.


So what we saw is that we can specify the Duration the page should be cached which is related to the talk about frequency we did earlier. The Duration should be chosen so that during that time we are not expecting any change in data and for the criteria, we saw how we can use VaryByParam to make sure that the output for every different criteria is generated and the cached copy is not just presented to the user.
If we need different output pages based on any/all of the HTML element change, we can specify the list of VaryByParam ="*". Let us look as some other parameters that we can use to customize caching behavior.
  • VaryByParam: List of strings that are sent to server via HTTP POST/GET that are checked to validate cache
  • VaryByCustom: Used for custom output cache requirements
  • VaryByHeader: HTTPs header that determines the cache validity
  • SqlDependency: Defines the Database-tablename pair on which the validity of cache depends

Cache Location

There is one more important property of the OutputCache attribute class which is Location. This property will determine where will the cached data be stored on the server. Possible values for this property can be:
  • Any (Default): Content is cached in three locations: the web server, any proxy servers, and the web browser.
  • Client: Content is cached on the web browser.
  • Server: Content is cached on the web server.
  • ServerAndClient: Content is cached on the web server and and the web browser.
  • None: Content is not cached anywhere.

Smarter ways to specify Cache attribute

If all our action methods have same caching needs then instead of adorning all the individual action methods with this attribute, we can simply go and adorn the controller with this attribute and the caching will be effective on all the aciton methods.

       [OutputCache(Duration = 30, VaryByParam = "none")]
    public class HomeController : Controller
    {   
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult About()
        {
            return View();
        }
     }

In case we have multiple action methods across controllers needing the same caching behavior, we can put this caching values in the web.config and create acacheprofile for it.

<caching>
  <outputCacheSettings>
    <outputCacheProfiles>
      <add name="MyCacheProfile"
           duration="30"
           varyByParam="id"
           location="Any" />
    </outputCacheProfiles>
  </outputCacheSettings>
</caching>

And to use these values in the action methods we just need to specify the CacheProfile name in the action method.

        [OutputCache(CacheProfile = "MyCacheProfile")]
        public ActionResult Index()
        {
            return View();
        }

Partial Page Caching

In asp.net Web forms, we need to create custom user controls in order to achieve partial page caching. Same can be achieved in the MVC world by creating a simple partial view. Caching in that partial view will be governed by the OutputCache attribute associated with the action method responsible to render the data in this partial view.

To Illustrate this let us create one more action method Index2 in the controller. This action will not cache the data. We will render a partial View in this Index2 View. The partial view will cache the time for 10 seconds. Lets look at the action methods for these.

        public ActionResult Index2()
        {
            return View();
        }

        [OutputCache(Duration = 10, VaryByParam = "none")]
        public PartialViewResult PartialTest()
        {
            return PartialView("SamplePartial");
        }

The Index2 View looks like:


@{
    ViewBag.Title = "Caching Demo";
}

Time is @DateTime.Now.ToString()

<br /><br />
Partial page here: @Html.Action("PartialTest")

And finally the partial view code:

Time @DateTime.Now.ToString()

Now if we run the application and navigate to Index2, we can see that the time from the main page is not getting cached but the the time coming from the partial view is getting cached for 10 seconds.

Application Caching

Application data caching is a mechanism for storing the Data objects on cache. It has nothing to do with the page caching. ASP.NET allows us to store the object in a Key-Value based cache. We can use this to store the data that need to cached. Let us work on the same example and try to store the DateTime string in the Application Cache now.

Let us create one action method which will display the date on the view from the application cache.

    public ActionResult Index3()
        {
            if (System.Web.HttpContext.Current.Cache["time"] == null)
            {
                System.Web.HttpContext.Current.Cache["time"] = DateTime.Now;
            }

     ViewBag.Time= ((DateTime)System.Web.HttpContext.Current.Cache["time"]).ToString();
            return View();
        }

The view corresponding to this action method is:


@{
    ViewBag.Title = "Caching Demo";
}

Time is @ViewBag.Time

Now if we run the application and navigate to Index3, we will see the time. But no matter how many times, we refresh this page, the time value will not change. Because the value is coming from the Application cache. Also, we are not invalidating the cache at all.



There are various parameters associated with application data caching that can be used to invalidate the value and control its behavior.
  • Dependencies: Any file or item in cache that invalidates this cache item
  • absoluteExpiration: Absolute time when this object should be removed from cache
  • slidingExpiration: Relative time when this object should be removed from the cache
  • priority: Defines the priority of the item. This is useful when server runs out of memory as in that case it start removing items from cache with lowest priority first
  • onRemoveCallBack: This is the event handler that will be called when the object is removed from cache. It gives us a place to take further actions.

one more helpfull link is Click here

Continue Reading →

Topics

ADFS (1) ADO .Net (1) Ajax (1) Angular (43) Angular Js (15) ASP .Net (14) Authentication (4) Azure (3) Breeze.js (1) C# (47) CD (1) CI (2) CloudComputing (2) Coding (7) CQRS (1) CSS (2) Design_Pattern (6) DevOps (4) DI (3) Dotnet (8) DotnetCore (16) Entity Framework (2) ExpressJS (4) Html (4) IIS (1) Javascript (17) Jquery (8) Lamda (3) Linq (11) microservice (3) Mongodb (1) MVC (46) NodeJS (8) React (11) SDLC (1) Sql Server (32) SSIS (3) SSO (1) TypeScript (1) UI (1) UnitTest (1) WCF (14) Web Api (15) Web Service (1) XMl (1)

Dotnet Guru Archives