5

I am working on exception handling and have written below code for the same.

Web.Config

<customErrors mode="On"></customErrors>

Code Changes

public class CustomExceptionFilter : HandleErrorAttribute
{
    public override void OnException(ExceptionContext filterContext)
    {

        //_logger.Error("Uncaught exception", filterContext.Exception);

        ViewResult view = new ViewResult();
        view.ViewName = "Error";
        filterContext.Result = view;

        // Prepare the response code.
        filterContext.ExceptionHandled = true;
        filterContext.HttpContext.Response.Clear();
        filterContext.HttpContext.Response.TrySkipIisCustomErrors = true;
    }
}

Global.asax

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();
    FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
    RouteConfig.RegisterRoutes(RouteTable.Routes);
    BundleConfig.RegisterBundles(BundleTable.Bundles);

    // To handle exceptions
    GlobalFilters.Filters.Add(new CustomExceptionFilter());

    var unityContainer = ModelContainer.Instance;
    DependencyResolver.SetResolver(new UnityDependencyResolver(unityContainer));
}

Error View

@*@model System.Web.Mvc.HandleErrorAttribute*@
<div class="row">
    <div class="col-sm-12">
        <h1>Error</h1>
        <div class="col-sm-12">
            <h2>An error occurred while processing your request.</h2>
        </div>
    </div>
</div>

In my error view, I want to show the exception message.

Also I have one more requirement to show different message in case of 404 error exists.

Nkosi
  • 235,767
  • 35
  • 427
  • 472
Gaurav123
  • 5,059
  • 6
  • 51
  • 81

3 Answers3

7
public class CustomExceptionFilter : HandleErrorAttribute {
    public override void OnException(ExceptionContext filterContext) {

        var controller = filterContext.Controller as Controller;
        controller.Response.StatusCode = (int)System.Net.HttpStatusCode.InternalServerError;
        controller.Response.TrySkipIisCustomErrors = true;
        filterContext.ExceptionHandled = true;

        var controllerName = (string)filterContext.RouteData.Values["controller"];
        var actionName = (string)filterContext.RouteData.Values["action"];
        var exception = filterContext.Exception;
        //need a model to pass exception data to error view
        var model = new HandleErrorInfo(exception, controllerName, actionName);

        var view = new ViewResult();
        view.ViewName = "Error";
        view.ViewData = new ViewDataDictionary();
        view.ViewData.Model = model;

        //copy any view data from original control over to error view
        //so they can be accessible.
        var viewData = controller.ViewData;
        if (viewData != null && viewData.Count > 0) {
            viewData.ToList().ForEach(view.ViewData.Add);
        }

        //Instead of this
        ////filterContext.Result = view;
        //Allow the error view to display on the same URL the error occurred
        view.ExecuteResult(filterContext);

        //should do any logging after view has already been rendered for improved performance.
        //_logger.Error("Uncaught exception", exception);

    }
}

Views/Shared/Error.cshtml

@model System.Web.Mvc.HandleErrorInfo
@{
    ViewBag.Title = "Error";
}
<div class="row">
    <div class="col-sm-12">
        <h1>Error</h1>
        <div class="col-sm-12">
            <h2>An error occurred while processing your request.</h2>
        </div>
        <div>
            @{
                if (Model != null && Model.Exception != null) {
                    <h5>Here is some information you can pass on to the administrator</h5>
                    <h3>Path: ~/@string.Format("{0}/{1}", Model.ControllerName, Model.ActionName)</h3>
                    <h4>Error: @Model.Exception.GetType().Name</h4>
                    if (Request.IsLocal) {
                        <h4>Message: @Model.Exception.Message</h4>
                        <h5>@Model.Exception.StackTrace</h5>
                    }
                }
            }
        </div>
    </div>
</div>

Web.Config

<customErrors mode="Off"/>
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • `` view.ExecuteResult(filterContext)`` is throwing exception – Gaurav123 Sep 01 '16 at 11:59
  • what error is it throwing? Make sure you have the error view in this location in project `Views/Shared/Error.cshtml` – Nkosi Sep 01 '16 at 12:02
  • An exception of type 'System.Web.HttpCompileException' occurred in System.Web.dll but was not handled in user code – Gaurav123 Sep 01 '16 at 12:05
  • Ok that error looks like it might be an issue in the error view. check this post and see if you can resolve it. http://stackoverflow.com/a/31609192/5233410 – Nkosi Sep 01 '16 at 12:09
  • Thanks...System.Web.Mvc.HandleErrorAttribute doesn't contain definition for ``Exception``, instead it has ``ExceptionType`` – Gaurav123 Sep 01 '16 at 12:16
  • This shows that the property should exist https://msdn.microsoft.com/en-us/library/system.web.mvc.handleerrorinfo(v=vs.118).aspx – Nkosi Sep 01 '16 at 12:19
  • Have you added anything extra to what I had in the view in the answer? – Nkosi Sep 01 '16 at 12:20
  • Oh I got it, you apparently wrote ``@model System.Web.Mvc.HandleErrorAttribute `` it should be ``@model System.Web.Mvc.HandleErrorInfo``....let me try and will let know in case of issue – Gaurav123 Sep 01 '16 at 12:21
  • Ouch. my bad. yeah thats the typo. I had copied it from you original question. – Nkosi Sep 01 '16 at 12:22
  • no problem...it is working but displaying the content of error page twice..any idea? – Gaurav123 Sep 01 '16 at 12:29
  • hmmmm...that is odd. Can you screenshot it and send a link if possible. – Nkosi Sep 01 '16 at 12:32
  • Just want to confirm that in my web.config I have ````... Do I need to make any changes? – Gaurav123 Sep 01 '16 at 12:34
  • yes that should be off. that is the culprit right there – Nkosi Sep 01 '16 at 12:34
  • awesome...it worked :) ..last question will it work for ``404 not found`` too ? – Gaurav123 Sep 01 '16 at 12:39
  • No that is a separate problem with a different workaround. – Nkosi Sep 01 '16 at 12:41
  • ok thanks...I tried this `` `` and it worked for 404 but causing twice error display – Gaurav123 Sep 01 '16 at 12:43
  • Ask it in another question and send me the link. Don't want to muddy up this answer. – Nkosi Sep 01 '16 at 12:44
  • Involves a `ErrorController`, some custom routes and the `httpErrors` in web config to get away from redirects – Nkosi Sep 01 '16 at 12:45
  • Thanks I have accepted the answer and will ask in separate question tomorrow. Thanks – Gaurav123 Sep 01 '16 at 12:49
  • Added new question :) http://stackoverflow.com/questions/39285429/how-to-handle-404-error-in-config-and-code-in-mvc5 – Gaurav123 Sep 02 '16 at 06:19
1

You can try sending like this

filterContext.HttpContext.Items["Exception"] = Exception.Message;
Nkosi
  • 235,767
  • 35
  • 427
  • 472
divya
  • 196
  • 11
0

I know this is an old post but I just want to share the easiest way to do it. Just paste this in your Web.config

 <system.web>
 <customErrors mode="On" defaultRedirect="~/home">
      <error statusCode="404" redirect="~/Error.html"/>
      <error statusCode="403" redirect="~/Error.html"/>
  </customErrors>
 <system.web>
MelPogz
  • 67
  • 2
  • 9