1

In my asp.net mvc application, I would like to show the user the error message that was used to throw an exception. The exception occurs in an ajax request. I have tried this:

In Global.asax.cs file, I have global application error handler:

protected void Application_Error(object sender, EventArgs e)
{
    Exception exception = System.Web.HttpContext.Current.Server.GetLastError();

    // do something so that client side gets the value exception.Message
    // I have tried these, but no success
    HttpContext.Current.Response.StatusDescription = exception.Message;
    HttpContext.Current.Response.StatusCode = 1000;  // custom status code
}

In javascript, I have global ajaxError handler:

$(document).ajaxError(function (xhr, props) {
    // show the message in the exception thrown on the server side
});

I tried to get the exception message in JavaScript using props.statusText, props.responseText, but none of them had the exception message.

My question: What can I do in the Application_Error method so that I can get the message contained in exception.Message to the global ajaxError function on the client side? Please note that I can easily handle exception that occurs in any specific Action where an ajax request hits, but I would like to make a global exception handler, that will allow me to just throw an exception with a message from any part of my application, and the exception message gets shown to the user on the client side.

I have tried this, but this doesn't solve my problem, because I want to use jQuery global ajaxError, instead of handling error in just a specific ajax request. Can this be modified to achieve what I want?

Sнаđошƒаӽ
  • 16,753
  • 12
  • 73
  • 90

1 Answers1

3

You can create a basecontroller and override the OnException method

public class BaseController : Controller
{
    protected override void OnException(ExceptionContext filterContext)
    {
        //your existing code to log errors here

        filterContext.ExceptionHandled = true;
        if (filterContext.HttpContext.Request.Headers["X-Requested-With"]
                                                                 == "XMLHttpRequest")
        {

            filterContext.Result = new JsonResult
            {
                JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                Data = new
                {
                    Error = true,
                    Message = filterContext.Exception.Message
                }
            };
            filterContext.HttpContext.Response.StatusCode = 500;
            filterContext.ExceptionHandled = true;
        }
        else
        {
            filterContext.Result = new RedirectToRouteResult(new RouteValueDictionary
                {{"controller", "Error"}, {"action", "Index"}});
        }
    }
}

and have all your controllers inherit from this

public class HomeController : BaseController
{

}

So any time an exception happens in your controllers, this OnException method will be executed and if it is an ajax request, It returns a json response with the below structure

{
  Error : true,
  Message : "The message from the exception caught"
}

and now in your javascript, wire up the global ajaxError event and you can read the response coming from server and parse it to a js object and then read the Message property

$(document).ready(function() {

    $(document).ajaxError(function (event, request, settings) {           
        var d = JSON.parse(request.responseText);
        alert("Ajax error:"+d.Message);               
    });

});
Shyju
  • 214,206
  • 104
  • 411
  • 497
  • I have already tried some similar code, but no success. Perhaps I wasn't using it the right way. Anway, I have a question, with this code in place, do I need to get rid of Application_Error in Global.asax? – Sнаđошƒаӽ Oct 02 '17 at 19:22
  • I wouldn't use Global.asax. When you decide to use ASPNETcore in future projects, it will not be available to you anymore. However, protected override void OnException(ExceptionContext filterContext){} will be, and it is used in your controller. – Jason Roner Oct 02 '17 at 19:50