Chart.js Asp.net : Create Pie chart with database jQuery Ajax C#

This article explains using Chart.js in Asp.net C# Web Application we can create a pie chart with database MS SQL server connectivity via jQuery ajax call.  You can also have a look on related article, .

Now in this post here we create a pie chart by using chart.js library and bind data from our database MS Sqlserver, with jQuery ajax calling.

Here we are creating a pie chart, which shows data from the database (Ms SQL server).  In my database, I have a table which stores data (website traffic source info).

So basically our pie chart data will shows traffic source info .i.e. (how much of page views referral by facebook, twitter, google+, Tumblr etc ).

Chart.js: Simple,clean and engaging charts for designers and developers developed by Nick Downie . It uses the HTML5 canvas element.

It’s supported in all modern browsers, and polyfills support for IE7/8. Chart.js is dependency free and super lightweight.

Download – Chart.js file and include in Asp.net Webform

First download and include latest files of the chart.js , jQuery library in your web page.

HTML markup under head tag looks like as shown below.

<head runat="server">
    <title>Pie Chart Asp.net with database ms sqlserver</title>
    <script src="js/jquery-1.10.2.min.js" type="text/javascript"></script>
    <script src="js/Chart.js" type="text/javascript"></script>
</head>

 

Html Markup (Design) – Adding HTML5 Canvas Tag

I have added 2 drop-down list control to select the year, month, along with a button and a  canvas tag.

Now on button click will call jQuery ajax, and then on ajax success our pie chart gets generated by using Chart.js library and HTML5 Canvas tag

<select id="ddlyear">
    <option>2010</option>
    <option>2011</option>
    <option>2012</option>
    <option>2013</option>
    <option>2014</option>
    <option>2015</option>
</select>
<select id="ddlMonth">
    <option value="1">Jan</option>
    <option value="2">Feb</option>
    <option value="3">Mar</option>
</select>
<button id="btnGeneratePieChart">Show</button>
<br/><canvas id="myChart" width="200" height="200"></canvas>

 

Code Behind – Ajax call WebMethod, and returns JSON format data to create Pie Chart

First add a WebMethod .i.e asmx file, and then we write our WebMethod which returns JSON format data, In our .asmx file will create a class named as trafficSourceData as shown below.

 public class trafficSourceData{
          public string label{get;set;}
          public string value{get;set;}
          public string color{get;set;}
          public string hightlight{get;set;}
    }

Now our WebMethod will pull data from database Ms Sqlserver for specific month and year, and return list of class object .i.e trafficSourceData class list as JSON formatted data, so our pie chart get created using chart.js.

[WebMethod]
    public List getTrafficSourceData(List gData)
    {
        List t = new List();
        string[] arrColor = new string[] { "#231F20", "#FFC200", "#F44937", "#16F27E", "#FC9775", "#5A69A6" };

        using (SqlConnection cn = new SqlConnection(conn))
        {
            string myQuery = "select * from traffic_data where YEAR =@year and MONTH=@month";
            SqlCommand cmd = new SqlCommand();
            cmd.CommandText = myQuery;
            cmd.CommandType = CommandType.Text;
            cmd.Parameters.AddWithValue("@year", gData[0]);
            cmd.Parameters.AddWithValue("@month", gData[1]);
            cmd.Connection = cn;
            cn.Open();
            SqlDataReader dr = cmd.ExecuteReader();
            if (dr.HasRows)
            {
                int counter = 0;
                while (dr.Read())  {
                    trafficSourceData tsData = new trafficSourceData();
                    tsData.value = dr["visit_count"].ToString();
                    tsData.label = dr["traffic_source"].ToString();
                    tsData.color = arrColor[counter];
                    t.Add(tsData);
                    counter++;
                }
            }
        }
        return t;
    }

 

jQuery –  initializing Chart.js in Asp.net WebPage

Now back to client side coding, we have already done with the server-side code by creating WebMethod which return JSON format data. So now in our Ajax call on success will initialize Chart.js variable.

Client-side code looks like as written below

$(document).ready(function () {

    $("btnGeneratePieChart").on('click', function (e) {
        e.preventDefault();
        var gData = [];
        gData[0] = $("#ddlyear").val();
        gData[1] = $("#ddlMonth").val();

        var jsonData = JSON.stringify({
            gData: gData
        });
        $.ajax({
            type: "POST",
            url: "WebService.asmx/getTrafficSourceData",
            data: jsonData,
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: OnSuccess_,
            error: OnErrorCall_
        });

        function OnSuccess_(response) {
            var aData = response.d;
            var arr = [];
            $.each(aData, function (inx, val) {
                var obj = {};
                obj.color = val.color;
                obj.value = val.value;
                obj.label = val.label;
                arr.push(obj);
            });
            var ctx = $("#myChart").get(0).getContext("2d");
            var myPieChart = new Chart(ctx).Pie(arr);
        }

        function OnErrorCall_(response) {}
        e.preventDefault();
    });
});

 

Finally, we are done with coding, Now every time we click button our pie chart gets created.

pieChartDB

Encrypting QueryStrings with .NET

Once upon a time in the tech world, obscurity was security - this being most true in the early years of the industry, when there were gaping holes in privacy policies and confidential client information was bandied about from site to site without a care as to who actually could read the information.

With the new Cryptography classes in .NET, there's absolutely no excuse for not hiding even the most innocuous user data. If you ever need to 'piggy-back' information from one web page to another, whether it is within a POST or a GET parameter, you're passing clear information that anyone can sniff - and that's a bad thing.

If you're not going to use a session variable for storing end user information, you're most likely going to keep some sort of State by passing the information to a cookie or push it around with GET/POST parameters. If you're passing around any sort of ID or user information like their name, it's better to err on the side of caution and encrypt the information.

GET Vs. POST

A POST parameter keeps the information out of the URL, but it can still be sniffed quite easily as it passes in clear text across your network or the Internet. Using POST will keep the mere curious at bay, as the information is not contained in the URL - but this will not stop someone determined to snag out your data.

A QueryString parameter passes information within the site's URL. Why would you even use a QueryString? Well, maybe you need to let your user bookmark a particular page, or maybe you have to refer directly to a page in a URL via a link - you can't do either if you're using POST. A QueryString puts data in the URL for the entire world to see, so if you don't know if the end user is malicious, I'd think hard about using a QueryString for anything but site-related information.

Be smart and encrypt any and all data you're moving around from page to page, especially if that information could be used maliciously. You may trust your users, but you still need that extra level of security that clear text GET/POST data doesn't provide.

Imagine this scenario - you've been passing the customer's ID in the database around in a QueryString, in a URL that looks like this:

http://yoursite.com?cust_id=29

You know what a user is going to do? Switch that 29 to a 30 or 12 or some other number, and if you're not checking for invalid requests, you'll be dishing up some other customer's data.

Enter Encryption

What I was looking for was a quick way to encrypt and decrypt parts of a QueryString - it had to be on the fly, quick and dirty.

I chose Base64 because it wouldn't throw bizarre characters in my QueryString that I couldn't pass around… Little did I know that I'd hit a snag while passing around my encrypted QueryString - Apparently, the Request.QueryString object interprets the '+' sign as a space! So, with a quick Replace function slapped on my decrypt string, no harm, no foul.

Symmetric Key

The whole trick to this working is that the QueryString is encrypted and decrypted with the same private key. This is the secret key - if anyone gets a hold of your key, they can decrypt the data themselves, so keep it a secret!

We're going to use a hard-to-crack 8 byte key, !#$a54?3, to keep parts of our QueryString secret.

Let's Walk through the C# portion of the code:

Notice our two functions that abstract the dirty work that our Encryption64 class. The first, encryptQueryString, is used to encrypt the value of a QueryString. The second, decryptQueryString, is used to decrypt the value of an encrypted QueryString.

public string encryptQueryString(string strQueryString) {
    ExtractAndSerialize.Encryption64 oES = 
        new ExtractAndSerialize.Encryption64();
    return oES.Encrypt(strQueryString,"!#$a54?3");
}

public string decryptQueryString(string strQueryString) {
    ExtractAndSerialize.Encryption64 oES = 
        new ExtractAndSerialize.Encryption64();
    return oES.Decrypt(strQueryString,"!#$a54?3");
}

If we wanted to encrypt our QueryString on our first page, we could do something like this:

string strValues = "search term";
string strURL = "http://yoursite.com?search=" 
    + encryptQueryString(strValues);
Response.Redirect(strURL);

Inside our code-behind in our second page, we pass the contents our QueryString to a variable named strScramble. After that, we replace the '+' signs that our wonderful Request.QueryString has replaced with a space. We pass that string into our function, decryptQueryString, and retrieve the decrypted string.

string strScramble =  Request.QueryString["search"];
string strdeCrypt = decryptQueryString(
    strScramble.Replace(" ", "+"));

Now we've decrypted the value of the QueryString, 'search', and we can do whatever we want with it. The end user is going to see a URL that looks like:

http://yoursite.com?search=da00992Lo39+343dw

They'll never be able guess what's going on in your QueryString, and if they try to fool around with it, there's no way to crack the code without knowing the Symmetric key.

VB.NET

Imports System
Imports System.IO
Imports System.Xml
Imports System.Text
Imports System.Security.Cryptography

Public Class Encryption64
    Private key() As Byte = {}
    Private IV() As Byte = {&H12&H34&H56&H78&H90&HAB&HCD&HEF}

    Public Function Decrypt(ByVal stringToDecrypt As String_
        ByVal sEncryptionKey As StringAs String
        Dim inputByteArray(stringToDecrypt.LengthAs Byte
         Try
            key = System.Text.Encoding.UTF8.GetBytes(Left(sEncryptionKey8))
            Dim des As New DESCryptoServiceProvider()
            inputByteArray = Convert.FromBase64String(stringToDecrypt)
            Dim ms As New MemoryStream()
            Dim cs As New CryptoStream(msdes.CreateDecryptor(keyIV), _
                CryptoStreamMode.Write)
            cs.Write(inputByteArray0inputByteArray.Length)
            cs.FlushFinalBlock()
            Dim encoding As System.Text.Encoding = System.Text.Encoding.UTF8
            Return encoding.GetString(ms.ToArray())
        Catch e As Exception
            Return e.Message
        End Try
    End Function

    Public Function Encrypt(ByVal stringToEncrypt As String_
        ByVal SEncryptionKey As StringAs String
        Try
            key = System.Text.Encoding.UTF8.GetBytes(Left(SEncryptionKey8))
            Dim des As New DESCryptoServiceProvider()
            Dim inputByteArray() As Byte = Encoding.UTF8.GetBytes_
                stringToEncrypt)
            Dim ms As New MemoryStream()
            Dim cs As New CryptoStream(msdes.CreateEncryptor(keyIV), _
                CryptoStreamMode.Write)
            cs.Write(inputByteArray0inputByteArray.Length)
            cs.FlushFinalBlock()
            Return Convert.ToBase64String(ms.ToArray())
        Catch e As Exception
            Return e.Message
        End Try
    End Function

End Class

Exception Handling in ASP.NET MVC

Index

Introduction

Exception handling is a serious matter in any application, whether it's web or desktop. Implementing a proper exception handling is important in any application. In most cases once we catch the exception we have to log the exception details to database or text file and show a friendly message to the user.

In ASP.NET applications, error handling is done mostly in two ways: at local level using try-catch blocks and at global level using application events. ASP.NET MVC comes with some built-in support for exception handling through exception filters. The HandleError is the default built-in exception filter. Unfortunately, the HandleError filter not gives a complete answer to the exception handling problem and that makes us to still rely on the Application_Error event.

In this article, we will learn about the HandleError filter and discuss about the different exception handling mechanisms that will fit to an MVC application.

HandleError Attribute

Exception filters

The exception filters are attributes that can be applied over an action or a controller or even at a global level. When you apply the filter at the global level then it will handle the exceptions raised by all the actions of all the controllers. The exception filters not only catches the exceptions that are raised by the actions but also the ones that are raised by the action filters that are applied over the actions.

All the exception filters implements the IExceptionFilter interface. Listing 1. shows the definition of this interface. The IExceptionFilter contains a single method called OnException which will be called whenever an exception occurs. The ExceptionContext parameter which derives from ControllerContext provides access to the controller, route data and HttpContext.

public interface IExceptionFilter
{
	void OnException(ExceptionContext filterContext);
}

Listing 1. IExceptionFilter definition

The HandleErrorAttribute is the default implementation of the IExceptionFilter. When you create a MVC application you will see the HandleErrorAttribute is added to the GlobalFiltersCollection in the Global.asax.cs.

public static void RegisterGlobalFilters(GlobalFiltersCollection filters)
{
	filters.Add(new HandleErrorAttribute());
}

Listing 2. Registering HandleErrorAttribute to GlobalFiltersCollection

What the HandleError filter does?

The HandleError filter handles the exceptions that are raised by the controller actions, filters and views, it returns a custom view named Error which is placed in the Shared folder. The HandleError filter works only if the <customErrors> section is turned on in web.config.

The HandleError filter handle exceptions only if the <customErrors> is turned on in web.config

Error View

The Error view that is created by default contains the following html.

@{
   Layout = null;
}

<!DOCTYPE html>
<html>
<head>
   <meta name="viewport" content="width=device-width" />
   <title>Error</title>
</head>
<body>
   <h2>
       Sorry, an error occurred while processing your request.
   </h2>
</body>
</html>

Listing 3. Error View

It contains nothing other than a simple text message. The Layout property is set to null so that the Error view doesn't inherits the application's style.

Accessing the exception details in Error view

In some cases, we have to access the exception information from the Error view. The HandleError filter not only just returns the Error view but it also creates and passes the HandleErrorInfo model to the view. The HandleErrorInfo model contains the details about the exception and the names of the controller and action that caused the exception.

Here is the definition of the HandleErrorInfo.

public class HandleErrorInfo
{   
	public HandleErrorInfo(Exception exception, string controllerName, 
		string actionName);

	public string ActionName { get; }

	public string ControllerName { get; }

	public Exception Exception { get; }
}

Listing 4. HandleErrorInfo error model

Though it's not necessary let's strongly type the Error view to the HandleErrorInfo model.

@model System.Web.Mvc.HandleErrorInfo

Listing 5. Strongly typing Error view to HandleErrorInfo model

We can easily show the exception and other information by accessing the model through the Model property.

<h2>Exception details</h2>
<p>
	Controller: @Model.ControllerName <br>
	Action: @Model.ActionName
	Exception: @Model.Exception
</p>

Listing 6. Displaying exception details in Error view

Returning different views for different exceptions

We can return different views from the HandleError filter. For ex. if you want to return one view for database exceptions and another view for application exceptions, you could easily do that by specifying the View and Exception properties as shown in the below listing.

[HandleError(Exception = typeof(DbException), View = "DatabaseError")]
[HandleError(Exception = typeof(AppException), View = "ApplicationError")]
public class ProductController
{
	
}

Listing 7. Setting views for exceptions

The HandleErrorAttribute can be applied multiple times over a controller or action or at global level.

Limitations of HandleError

The HandleError filter has some limitations by the way.

1. Not support to log the exceptions
2. Doesn't catch HTTP exceptions other than 500
3. Doesn't catch exceptions that are raised outside controllers
4. Returns error view even for exceptions raised in AJAX calls

Let see one by one.

1. Not support to log the exceptions

Logging is very important in error handling and even simple applications get much benefit by logging the errors to a text file or database. The HandleError filter suppresses the exceptions once they are handled and all it does is showing a custom view to the user.

2. Doesn't catch HTTP exceptions other than 500.

The HandleError filter captures only the HTTP exceptions having status code 500 and by-passes the others. Let's assume we have an action that returns all the posts published for a particular category. If the category not exists then we are throwing a 404 HTTP exception.

public ViewResult Posts(string category)
{
	if(_blogRepository.Category(category) == null)
		throw new HttpException(404, "Category not found");

	return _blogRepository.Posts(category);
}

Listing 8. Throwing HttpException from action

If any user passes an invalid category a 404 exception will be thrown from the action and the HandleError don't catch this error. Usually in this case, programmers like to show a custom view with a message "The requested category is not found or invalid". Not only the 404 exceptions, the HandleError doesn't catch any HTTP exception other than 500.

Handling the HTTP exceptions in filters is right or wrong is a thing for debate. In some cases we may have to bypass the HTTP exceptions to the framework to take proper action against it. So handling HTTP exceptions in filters depends upon the application and it's not mandatory.

3. Doesn't catch exceptions that are raised outside controllers

The HandleError is an exception filter and exception filters are called only if any exception happens inside the action or in the action filters that are applied over the action. So if the exception happens some other place the filter will be silent.

For ex. say we have set up a route constraint for a specific route as shown in the below listing.

routes.MapRoute(
	 "Default", 
	 "Strange~Action",
	 new { controller = "NonIE", action = "Action"  },
	 new { browserConstraint = new UserAgentConstraint("IE") } 
);

Listing 9. Adding constraints to routes

Route Constraints restricts a route against matching URLs.

The UserAgentConstraint that we set up in the above route restricts the route to handle requests from only Internet Explorer browsers. In the implementation of UserAgentConstraint I'm purposely throwing an exception.

public class UserAgentConstraint : IRouteConstraint
{
	private readonly string _restrictAgent;

	public UserAgentConstraint(string restrictAgent)
	{
		_restrictAgent = restrictAgent;
	}

	public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
	{
	  // TODO: return true if the browser is not restricted one.
		throw new NotImplementedException("You forget to implement me");
	}
}

Listing 9. UserAgentConstraint

This exception is thrown at very early stage and HandleError filter won't be there to catch this. When we access the route where the above constraint is applied we will see the yellow screen instead of the custom error page.

4. Return error view even in exceptions occurred in AJAX calls.

In case of AJAX calls, if some exception happens the HandleError filter returns the custom error view, which is not useful in the client-side. It would be great to return a piece of JSON in AJAX exceptions and for that we have to extend the HandleError filter or have to create a custom exception filter.

HandleError vs. Application_Error

Exception filters are not global error handlers and this is an important reason that forces us to still rely on Application_Error event. Some programmers don't even use the HandleError filter in their application at all and use only the Application_Error event for doing all the error handling and logging work. The important problem we face in the Application_Error event is, once the program execution reaches this point then we are out of MVC context and because of that we can miss some context information related to the exception.

Another important feature that exception filters brings to us is we can handle the exceptions in different ways at different scopes, this is important in some cases, for ex. when exceptions are raised from one controller we have to return a custom error view and for other controllers we have to return a different error view, this could be easily accomplished through exception filters but not easily through the Application_Error event.

The bottom-line is, we need to use the Application_Error event at most of the cases in applications unless we are using a framework like ELMAH which magically handles all the exceptions. But whether we need to use the HandleError filter or not is totally depend upon the application. When we need a controller or action level exception handling then we can use the HandleError filter along with the Application_Error event else we can simply ignore the HandleError filter.

Extending HandleError

Most of the cases we have to extend the built-in HandleError filter or have to create a custom exception filter to do some useful job like logging. Here is an example that shows how to extend the built-in filter to log the exceptions using log4net and return a JSON object for AJAX calls.

public class CustomHandleErrorAttribute : HandleErrorAttribute
{
	private readonly ILog _logger;

	public CustomHandleErrorAttribute()
	{
		_logger = LogManager.GetLogger("MyLogger");
	}

	public override void OnException(ExceptionContext filterContext)
	{
		if (filterContext.ExceptionHandled || !filterContext.HttpContext.IsCustomErrorEnabled)
		{
			return;
		}

		if (new HttpException(null, filterContext.Exception).GetHttpCode() != 500)
		{
			return;
		}

		if (!ExceptionType.IsInstanceOfType(filterContext.Exception))
		{
			return;
		}

		// if the request is AJAX return JSON else view.
		if (filterContext.HttpContext.Request.Headers["X-Requested-With"] == "XMLHttpRequest")
		{
			filterContext.Result = new JsonResult 
			{ 
				JsonRequestBehavior = JsonRequestBehavior.AllowGet, 
				Data = new 
				{ 
					error = true,
					message = filterContext.Exception.Message
				} 
			};
		}
		else
		{
			var controllerName = (string)filterContext.RouteData.Values["controller"];
			var actionName = (string)filterContext.RouteData.Values["action"];
			var model = new HandleErrorInfo(filterContext.Exception, controllerName, actionName);
			
			filterContext.Result = new ViewResult
			{
				ViewName = View,
				MasterName = Master,
				ViewData = new ViewDataDictionary<HandleErrorInfo>(model),
				TempData = filterContext.Controller.TempData
			};
		}

		// log the error using log4net.
		_logger.Error(filterContext.Exception.Message, filterContext.Exception);

		filterContext.ExceptionHandled = true;
		filterContext.HttpContext.Response.Clear();
		filterContext.HttpContext.Response.StatusCode = 500;

		filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;      
	}
}

Listing 10. Extending HandleError

Most of the code are same as in the built-in filter. Notice we have ignored the HTTP exceptions so anyway we need to wire-up the Application_Error event to catch and log the missed exceptions. If the request is an AJAX call then we are returning a JSON object that contains a boolean and the exception message else we are returning the error view. We are setting the response status code as 500 and the HandleError filter also does the same, this is important in terms of REST and HTTP standards.

Returning views from Application_Error

In some applications we have to depend upon the Application_Error event for handling all the exceptions or the ones that are missed by the exception filters. Mostly programmers like to return an MVC view instead of a static page. Though we are out of the MVC context still we can return a view using a controller (thanks to StackOverflow).

Let's create an Error controller that return different views for different errors as shown in the below listing.

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

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

Listing 11. Error Controller

We have to invoke this Error controller from the Application_Error to return a view after the exception is logged.

protected void Application_Error(object sender, EventArgs e)
{
	var httpContext = ((MvcApplication)sender).Context;
	var currentController = " ";
	var currentAction = " ";
	var currentRouteData = RouteTable.Routes.GetRouteData(new HttpContextWrapper(httpContext));

	if (currentRouteData != null)
	{
		if (currentRouteData.Values["controller"] != null && !String.IsNullOrEmpty(currentRouteData.Values["controller"].ToString()))
		{
			currentController = currentRouteData.Values["controller"].ToString();
		}

		if (currentRouteData.Values["action"] != null && !String.IsNullOrEmpty(currentRouteData.Values["action"].ToString()))
		{
			currentAction = currentRouteData.Values["action"].ToString();
		}
	}

	var ex = Server.GetLastError();
	var controller = new ErrorController();
	var routeData = new RouteData();
	var action = "Index";

	if (ex is HttpException)
	{
		var httpEx = ex as HttpException;

		switch (httpEx.GetHttpCode())
		{
			case 404:
				action = "NotFound";
				break;

			// others if any
		}
	}

	httpContext.ClearError();
	httpContext.Response.Clear();
	httpContext.Response.StatusCode = ex is HttpException ? ((HttpException)ex).GetHttpCode() : 500;
	httpContext.Response.TrySkipIisCustomErrors = true;
	
	routeData.Values["controller"] = "Error";
	routeData.Values["action"] = action;

	controller.ViewData.Model = new HandleErrorInfo(ex, currentController, currentAction);
	((IController)controller).Execute(new RequestContext(new HttpContextWrapper(httpContext), routeData));
}

Listing 12. Returning views from Application_Error

We are doing many things in the above code, mainly we are instantiating the Error controller and invoking it by calling the Execute() method passing the HandleErrorInfo model and this is the model used by the HandleError filter as well. To know the controller and action that handled the request we have to access the GetRouteData method of RouteTable.Routes passing the httpcontext.

We are using a switch statement just to demonstrate how we can return different error views for different HTTP exceptions. If you want to take care of AJAX calls you have to change the implementation little as we did in the custom HandleError filter but to keep things simple I've ignored that part.

ELMAH

ELMAH (Error Logging Modules and Handlers) is an application-wide error logging facility that is completely pluggable. You can easily configure ELMAH for an ASP.NET MVC application without much code. The other benefits brought up by ELMAH is, it provides a custom page where the admin can view the errors including the original yellow screen, also it provides options to send emails, generate RSS etc.

ELMAH logs only unhandled exceptions so we have to signal ELMAH to log the exceptions that are handled. When we use the HandleError filter and ELMAH in an application we will confused seeing no exceptions are logged by ELMAH, it's because once the exceptions are handled by the HandleError filter it sets the ExceptionHandled property of the ExceptionContext object to true and that hides the errors from logged by ELMAH. A better way to overcome this problem is extend the HandleError filter and signal to ELMAH as shown in the below listing.

public class ElmahHandleErrorAttribute : HandleErrorAttribute
{
	public override void OnException(ExceptionContext filterContext)
	{
		var exceptionHandled = filterContext.ExceptionHandled;
		
		base.OnException(filterContext);
		
		// signal ELMAH to log the exception
		if (!exceptionHandled && filterContext.ExceptionHandled)
			ErrorSignal.FromCurrentContext().Raise(filterContext.Exception);
	}
}

Listing 13. Signaling to Elmah

Summary

In this article we saw about the built-in HandleError filter available with ASP.NET MVC to handle the exceptions. The HandleError filter has some limitations and most importantly it doesn't handle all the exceptions that are raised by the application.

Although HandleError filter bring some benefits in customizing error handling at a controller or action level still we have to rely on the Application_Error event. ELMAH is an error handling module that is easily pluggable to an ASP.NET application. Unlike HandleError, ELMAH catches all the exceptions raised by the application.

ExceptionHandling.zip (1.9MB)

OGData extension for BlogEngine.NET

Since Facebook launched their share link feature anyone including you can share your site or pages to their friends. You can tailor what is displayed on the Facebook wall in terms of title, description image and URL.

Facebook is smart enough to use the html meta tags on your page for title and description and it may list some or all of the <img> tags to the user to choose from. This is great as a starting point and may be enough in many cases, however in some it is not.

example_ogdata

Say that you put a Like button on a page. What happens when a user Likes it is that Facebook uses the title and description as before but it may try to pick an image from the page, probably closest in proximity to the Like button. This may not be what you want as you might want a specific image to be displayed on Likes.

Open Graph protocol

The Open Graph protocol enables you to integrate your web pages into the Facebook social graph. You can turn your pages into graph objects by adding additional meta information.

Additional images

One image may not be enough e.g. when users share your page with the above mentioned Share link feature. To still enable users to pick one of the images on your page you can add additional og:image <meta> tags to the header.

BlogEngine.NET

If you have BlogEngine.NET, I created an extension to insert automatically og data.

image

Here you will find two settings:

Then click the Add button and then click the Save button.

You can find the source code on GitHub.

Advertsing

125X125_06

TagCloud

MonthList

CommentList