Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enable custom errors in Azure

I am unable to set IIS to serve my custom error pages for errors outside of the MVC pipeline. If I throw an exception inside a controller it's all file, the Application_Error event handles that:

    protected void Application_Error(object sender, EventArgs e)
    {
        var error = Server.GetLastError();

        var routeData = new RouteData();
        routeData.Values["Controller"] = "Error";
        routeData.Values["Area"] = "";
        routeData.Values["Exception"] = error;

        if (error is HttpException)
        {
            switch (((HttpException)error).GetHttpCode())
            {
                case 401:
                    routeData.Values["Action"] = "NotAllowed";
                    break;

                case 403:
                    routeData.Values["Action"] = "NotAllowed";
                    break;

                case 404:
                    routeData.Values["Action"] = "NotFound";
                    break;
                default:
                    routeData.Values["Action"] = "ServerError";
                    break;
            }
        }
        else
        {
            routeData.Values["Action"] = "ServerError";
        }

        Response.Clear();
        Server.ClearError();

        IController controller = new ErrorController();
        controller.Execute(new RequestContext(new HttpContextWrapper(((MvcApplication)sender).Context), routeData));
    }

However, if I browse to a non-existent URL, IIS will handle the 404 error (or any other error), giving me the standard IIS error message and completely ignoring my web.config settings:

 <system.web>
  <customErrors mode="On" redirectMode="ResponseRewrite" defaultRedirect="/error">
    <error statusCode="401" redirect="/error/notallowed" />
    <error statusCode="403" redirect="/error/notallowed" />
    <error statusCode="404" redirect="/error/notfound" />
    <error statusCode="500" redirect="/error/servererror" />
  </customErrors>
</system.web>

<system.webServer>
  <httpErrors errorMode="Custom" defaultResponseMode="ExecuteURL">
    <clear />
    <error statusCode="401" path="/error/notallowed" />
    <error statusCode="403" path="/error/notallowed" />
    <error statusCode="404" path="/error/notfound" />
    <error statusCode="500" path="/error/servererror" />
  </httpErrors>
</system.webServer>

IIS default error page

/error/* is handled by a controller inside my application. What can I do to make IIS execute the custom error path, instead of feeding me the standard error page?

This is ASP.NET MVC 3, running on Azure. It doesn't work under straight IIS either, but the development server does execute the controller.

like image 920
CMircea Avatar asked Apr 07 '12 22:04

CMircea


3 Answers

IIS does not respect defaultResponseMode. You must add responseMode to each and every error, like so:

<httpErrors errorMode="Custom">
  <clear />
  <error statusCode="401" path="/error/notallowed" responseMode="ExecuteURL" />
  <error statusCode="403" path="/error/notallowed" responseMode="ExecuteURL" />
  <error statusCode="404" path="/error/notfound" responseMode="ExecuteURL" />
  <error statusCode="500" path="/error/servererror" responseMode="ExecuteURL" />
</httpErrors>

Why default doesn't apply is beyond me.

like image 59
CMircea Avatar answered Oct 16 '22 09:10

CMircea


I had exactly this problem and I was on Azure, the following solved it for me:

    Response.TrySkipIisCustomErrors = true;
like image 24
David Martin Avatar answered Oct 16 '22 10:10

David Martin


I found many solution accross web, but neither was working also for static files (for example for non-existing 'picture.jpg').

This solution works for me on both Azure WebSites and also on Azure WebRole instance. I use web.config transformations so update it to you own needs accordingly.

I use ASPX pages for errors so I can set correct HTTP response code (IIS always sets HTTP 200, when I used .htm pages)

File ~/404.aspx is:

<%@ Page Language="C#" AutoEventWireup="false" ContentType="text/html" Debug="false" EnableEventValidation="false" EnableSessionState="False" EnableViewState="false" ResponseEncoding="utf-8" Transaction="Disabled" ValidateRequest="false" ViewStateMode="Disabled" %>
<% Context.Response.StatusCode = 404; %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>404 Error - Page not found</title>
</head>
<body>
  <h1>Custom 404 page</h1>
</body>
</html>

File ~/500.aspx is:

<%@ Page Language="C#" AutoEventWireup="false" ContentType="text/html" Debug="false" EnableEventValidation="false" EnableSessionState="False" EnableViewState="false" ResponseEncoding="utf-8" Transaction="Disabled" ValidateRequest="false" ViewStateMode="Disabled" %>
<% Context.Response.StatusCode = 500; %>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>500 Server Error</title>
</head>
<body>
  <h1>Custom 500 page</h1>
</body>
</html>

Neccessary parts from ~/Web.config contains:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <customErrors mode="Off" />
  </system.web>

  <system.webServer>
    <httpErrors errorMode="Detailed" />
  </system.webServer>
</configuration>

Neccessary parts from ~/Web.Release.config contains:

<?xml version="1.0"?>
<configuration>
  <customErrors mode="On" defaultRedirect="/500.aspx" redirectMode="ResponseRewrite" xdt:Transform="Replace">
    <!-- AWARE do NOT use address in form "~/404.htm" but in "/404.htm" -->
    <error statusCode="404" redirect="/404.aspx" />
    <error statusCode="500" redirect="/500.aspx"/>
  </customErrors>

  <system.webServer>
    <httpErrors errorMode="Custom" existingResponse="Replace" xdt:Transform="Replace">
      <!-- AWARE do NOT use address in form "~/404.htm" but in "/404.htm" -->
      <remove statusCode="404" />
      <error statusCode="404" path="/404.aspx" responseMode="ExecuteURL" />

      <remove statusCode="500" />
      <error statusCode="500" path="/500.aspx" responseMode="ExecuteURL" />
    </httpErrors>
  </system.webServer>
</configuration>

The end.

like image 37
DHlavaty Avatar answered Oct 16 '22 10:10

DHlavaty