简体   繁体   中英

How to handle an exception only once in asp.net mvc

I want to log exception in my ASP.Net MVC 5 application. After researching here in stackoverflow and elsewhere, I found several ways for exception logging in.Net applications. I've my custom errors mode on in Web.config with 500 and 404 error status code redirection. As suggested by different opinion, Application_Error in Global.asax is always good to have to catch some out of the box exception and an OnException overrride method in a base controller to catch any inherited controller or action method exception.

But the issue I found, Application_Error is not providing much of specific details about the exception and same exception is bubbling up in Application_Error even if it is catched in BaseController OnException method. The way I'm doing this in OnException is kind of following-

    protected override void OnException(ExceptionContext filterContext)
    {
        var ex = filterContext.Exception;
        filterContext.ExceptionHandled = true;
        Server.ClearError();
        base.OnException(filterContext);
    }

Is it really possible to restrict an exception not bubbling up to Application_Error which was handled in OnException method? I'm also wondering if it's possible to get exception specific details in Application_Error .

Exception handling in ASP.NET MVC

Create a custom “HandleErrorAttribute” class:

public class CustomErrorHandler : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {
        //If the request is AJAX return JSON, else return View
        if (filterContext.HttpContext.Request.IsAjaxRequest() && filterContext.Exception != null)
        {
            // Log exception first
            filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

            filterContext.Result = new JsonResult
            {
                Data = new
                {
                    success = false,
                    message = "An error occured while sending form.",
                    type = filterContext.Exception.GetType().Name,
                    exception = filterContext.Exception.ToString()

                    //Message = "Error Processing your request. Technical detail: " + filterContext.Exception.Message,
                    //TechnicalDetails = filterContext.Exception.Message + System.Environment.NewLine + filterContext.Exception.StackTrace
                },
                JsonRequestBehavior = JsonRequestBehavior.AllowGet
            };

            // Let the system know that the exception has been handled
            filterContext.ExceptionHandled = true;
            filterContext.HttpContext.Response.Clear();

            // Avoid IIS7 getting in the middle
            //Response.TrySkipIisCustomErrors = true;
        }
        else
        {
            // Normal Exception. So, let it handle by its default ways
            base.OnException(filterContext);
        }
        // Write error logging code here if you wish.

        // If want to get different of the request
        //var currentController = (string)filterContext.RouteData.Values["controller"];
        //var currentActionName = (string)filterContext.RouteData.Values["action"];
    }
}

Decorate this class as attribute across controller or action method (no need to use try-catch block)

[CustomErrorHandler]
public JsonResult DeleteConfirmed(int id)
{
    if (ModelState.IsValid)
    {
        Schedule schedule = repository.Schedules.FirstOrDefault(m => m.Id == id);
        if (schedule == null)
        {
            return Json(new { success = false, message = "User not found." });
        }
        else
        {
            Schedule deletedSchedule = repository.DeleteSchedulePermanently(id);
            if (deletedSchedule != null)
            {
                return Json(new { success = true, message = "Succeeded" });
            }
        }
    }
    // If we got this far, something failed, redisplay form
    return Json(new { success = false, message = "Please check errors." });
}

In AJAX call, obtain the exception properties created in custom “HandleErrorAttribute” class.

$.ajax({

    //code omitted for brevity 

    error: function (jqXHR, textStatus, errorThrown) {
        if (jqXHR.status == 401) {
            // perform a redirect to the login page since we're no longer authorized
        }
        if (jqXHR.responseJSON != null) {
            displayAlert('danger', 'warning', jqXHR.responseJSON.message + " Error Details: " + jqXHR.responseJSON.exception, '#result');
        }
    },
    success: function (response, textStatus, XMLHttpRequest) {
        if (response.success) {
            showToast('success', 'Result', response.message, 'toast-top-right');
        }
        else {
            displayAlert('danger', 'warning', response.message, '#result');
        }
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM