Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Mark Olbert 87 posts 116 karma points
    Oct 26, 2009 @ 23:27
    Mark Olbert
    3

    Custom Error Page

    Is it possible to configure a "catch all" custom error page within Umbraco that will display if there's an unhandled exception thrown somewhere within a site?

    - Mark

  • Nico Lubbers 151 posts 172 karma points
    Oct 26, 2009 @ 23:39
    Nico Lubbers
    1

    Yes its very easy:

    For a 404: just make one page in umbraco and set its nodeid in the error404 tag in the /config/umbracoSettings.config file

    For a 500: you can put the fallback in the customError tag in the web.config

     

  • Nico Lubbers 151 posts 172 karma points
    Oct 26, 2009 @ 23:48
    Nico Lubbers
    5

    Like this:

            <customErrors mode="On" defaultRedirect="~/error.aspx">

     

  • Chad Rosenthal 271 posts 473 karma points
    Jan 08, 2010 @ 18:07
    Chad Rosenthal
    0

    Question: is this solely using .net functionality, or is their an umbraco handler dealing with this.

    Right now, it's throwing a 302: Temporary Redirect. Technically, this isn't correct since it should be throwing a 500. The page would then display the page instead of the requested page. Similar to how the regular 404 is currently handling.

    Just curious if this is worth my time investigating, or if it's 'just how it works' and I should just deal.

    -C

     

     

  • Mike 3 posts 23 karma points
    Mar 04, 2010 @ 20:32
    Mike
    0

    I am in need of a solution for 500 errors as well. We need to change the 500 server response to a 404 server response. Can someone please show me where Umbraco is handling its application error handling so that I can add a 500 function to it.

  • Greg 14 posts 34 karma points
    Dec 14, 2010 @ 12:53
    Greg
    0

    Bump!

    How can you configure a custom 500 that responds with a 500 status code rather than the default ASP.NET 302

  • Murray Roke 441 posts 798 karma points c-trib
    Mar 22, 2011 @ 02:41
    Murray Roke
    1

    One way is to write your own Error Handling Module, something like

    class ErrorHandlingModule : IHttpModule
        {
            public void Init(HttpApplication context)
            {
                Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~/");
                CustomErrorsSection section = (CustomErrorsSection)configuration.GetSection("system.web/customErrors");

                if(section.Mode != CustomErrorsMode.Off)
                    context.Error += Context_Error;
            }

            void Context_Error(object sender, EventArgs e)
            {
                var Response = HttpContext.Current.Response;
                var Server = HttpContext.Current.Server;

                if (/*check we're not already on error page, and perhaps check if we're remoteOnly errors.*/)
                {
                    Exception exception = Server.GetLastError().GetBaseException();
                    Response.StatusDescription = exception.Message;

                   if (/*test for certain types of exceptions which match differnt response codes*/)
                   {
                        Response.StatusCode = (int)HttpStatusCode.Forbidden;
                        Response.StatusDescription = exception.Message;
                        Server.Transfer("/Error.aspx");
                    }
                    /*..more exception types..*/
                    else
                    {
                        Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                        Server.Transfer("/Error.aspx");
                    }
                }
            }

            public void Dispose()
            {
                //nothing to clean up.
            }
        }

  • Andy 10 posts 31 karma points
    Nov 29, 2011 @ 18:52
    Andy
    0

    Murray's answer worked for me. I wanted to place the class in a helper assembly I wrote, so I thought for the benefit of anyone else who wants to try it, I'd mention that I had to register the module twice:

    <system.web>
       <httpModules>
          <add name="ErrorHandlingModule" type="HelperAssembly.ErrorHandlingModule, HelperAssembly" />
       </httpModules>
    </system.web>
    <system.webServer>
       <modules runAllManagedModulesForAllRequests="true">
          <add name="ErrorHandlingModule" type="HelperAssembly.ErrorHandlingModule, HelperAssembly" />
       </modules>
    </system.webServer>

    One other thing to mention is that I wanted to use a node as my error page. Server.Transfer didn't work for that, presumably because the "page" I was transferring to doesn't exist as a file on the server. Fortunately I found a workaround for that, at http://our.umbraco.org/forum/using/ui-questions/3862-Usercontrol-Servertransfer?p=0

    Worked great once I did that! Thanks!

  • Murray Roke 441 posts 798 karma points c-trib
    Nov 29, 2011 @ 21:14
    Murray Roke
    1

    @Nico, one thing you need to be aware of, is that your solution does not return the correct HTTP response code.

    I've actually simplified my solution since writing the above to 'mostly' use the built in machanism with just a handler to correct the http response codes.

    @Andy, the below solution is not designed work with content from the CMS,  I wanted to avoid that because if some kind of CMS problem is causing the exception you will get unexpected results.

    So first setup errors similar to nico's suggestion like so, with the important difference being redirectMode="ResponseRewrite" this will ensure the HTTP response code is not 302 (which is just wrong: I'm talking to you @microsoft)

    <customErrors mode="RemoteOnly" redirectMode="ResponseRewrite" defaultRedirect="/Error.aspx" />

    The other part is the handler to ensure the correct HTTP response codes: (and catch a few edge cases)

    class FixHttpStatusCodes : IHttpModule
    {
        private string defaultRedirect = null;
    
        public void Init(HttpApplication context)
        {
            Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~/");
            CustomErrorsSection section = (CustomErrorsSection)configuration.GetSection("system.web/customErrors");
            if (section != null && section.DefaultRedirect != null)
                defaultRedirect = section.DefaultRedirect;
    
            context.Error += Context_Error;
        }
    
        void Context_Error(object sender, EventArgs e)
        {
            var Response = HttpContext.Current.Response;
            var Server = HttpContext.Current.Server;
    
            Exception exception = Server.GetLastError().GetBaseException();
            Response.StatusDescription = exception.Message;
    
            if (exception is HttpRequestValidationException)
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
            else if (exception is HttpException && Regex.IsMatch(exception.Message, @"^The file '[^']*' does not exist\.$"))
                Response.StatusCode = (int)HttpStatusCode.NotFound;
            else if (exception is HttpException && Regex.IsMatch(exception.Message, @"^Path '[^']*' is forbidden\.$"))
            {
                Response.StatusCode = (int)HttpStatusCode.Forbidden;
                Response.StatusDescription = exception.Message;
            }
            else if (exception is HttpException && exception.Message.StartsWith("Maximum request length exceeded."))
            {
                Response.StatusCode = (int)HttpStatusCode.BadRequest;
                Configuration configuration = WebConfigurationManager.OpenWebConfiguration("~/");
                HttpRuntimeSection section = (HttpRuntimeSection)configuration.GetSection("system.web/httpRuntime");
                Response.StatusDescription = string.Format("Uploads must be less than {0:n0}KB.", section.MaxRequestLength);
                if(!string.IsNullOrEmpty(defaultRedirect))
                    Server.Transfer(defaultRedirect); // need to transfer for this one.
            }
            else if (exception is FileNotFoundException && exception.Message.IndexOf("Could not find file") == -1) // page not found exceptions don't include the text "Could not find file"
            {
                Response.StatusCode = (int)HttpStatusCode.NotFound;
            }
            else
            {
                Response.StatusCode = (int)HttpStatusCode.InternalServerError;
            }
        }
    
        public void Dispose()
        {
            //nothing to clean up
        }
    }

    Then you register the handler as shown by Andy's message.

  • saif 68 posts 88 karma points
    Apr 12, 2012 @ 12:14
    saif
    0

    Hi Murray and Andy,

    I implemented and registered the above code (httpModule)

    and

    I created a control in usercontrols/Test_WebUserControl.ascx  and intentionally I wrote some incorrect code in the control.

    Httpmodule does not redirect to error page neither it record error to database table [umbracoLog] instead it gives me error!

    Error creating control (usercontrols/Test_WebUserControl.ascx).
    Maybe file doesn't exists or the usercontrol has a cache directive, which is not allowed! See the tracestack for more information!

     

    Please could you advise, do I need to follow different steps to catch error in usercontrol.

    kind regards

    saif

  • maanehunden 61 posts 105 karma points
    Jan 07, 2014 @ 15:42
    maanehunden
    0

    Why not extend Application_Error in Global.asax to do your bidding ? 

  • Jacob 41 posts 90 karma points
    Jul 28, 2014 @ 19:37
    Jacob
    0

    Does Umbraco.Log store application errors that occur through IIS or unhandled exceptions?

     


    Edit:  It would appear not.   Is there any way to handle application errors through a BaseActionInvoker or similar methods used by MVC?  I've seen applications that use a BaseActionInvoker on a base controller class to encapsulate actions within a try/catch loop so that exception details can be logged to a database.  However, being that umbraco uses its own routing system outside of standard MVC, I'm not sure if a similar approach is possible.

  • Jacob 41 posts 90 karma points
    Jul 29, 2014 @ 16:09
    Jacob
    0

    So a BaseActionInvoker was the not solution in my environment.  Instead, I added an OnException event to a base surface controller and inherited that controller on all my umbraco controllers.  This enabled the ability to log all application errors.  Other errors are handled through the umbraco 404 page.

     

     

    protected override void OnException(ExceptionContext filterContext)
    { Exception e = filterContext.Exception;
    //Log Exception e filterContext.ExceptionHandled = true;
    //Add code to log exception
    filterContext.Result = new ViewResult() { ViewName = "Error" };
    }

Please Sign in or register to post replies

Write your reply to:

Draft