Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IIS Serves Custom Error page as plain text, no content-type header

UPD: Here is the full solution for error handling

I've got plain vanilla MVC4 web-project. Nothing added, nothing deleted, just created a new project in Visual Studio.

In web.config I've added custom error page handler:

<customErrors mode="On" defaultRedirect="~/Content/Error.htm" redirectMode="ResponseRewrite" />

and the ~/Content/Error.htm file is:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title>OOPS! Error Occurred. Sorry about this.</title>
</head>
<body>
    <h2>OOPS! Error Occurred</h2>
</body>
</html>

Whenever I get a 404 error on the site, Error.htm is served as plaintext in Firefox and Chrome:

HTML is displayed as plain text

Fiddler says that error page is served without content-type header which leads browsers to render the page as plain-text:

No Content-type header

Is there a way to force IIS server error pages with content-type header??

p.s. the actual problem is in a complex MVC4 project, that has it's own error handling in Global.asax. But I found that some errors don't go through the ASP pipe and handled only by IIS. Like dot at the end of the url. Solution with < httpErrors /> does serve correct responses, but our custom error handling in Global.asax, Application_Error() is not getting called this way.

UPD Seems like I can't win this war. IE displays that html properly rendered, Firefox and Chrome shows as plain text. When I switch to plain-text, Firefox and IE shows white-space correctly, IE swallows white-space and tries to render html. If I try serve an image as error page, Firefox and Chrome show image. IE shows this: IE9 is on crack! Facepalm!

like image 770
trailmax Avatar asked Mar 13 '13 11:03

trailmax


People also ask

How do I enable an error page in IIS?

To Enable detailed IIS Error messages:Open Internet Information Services (IIS) Manager. Select "Error Pages" Select "Edit Feature Settings" Select "Detailed Errors"


2 Answers

Use .aspx instead of .htm for error pages (rename htm to aspx).

<customErrors mode="On" defaultRedirect="~/Content/Error.aspx" redirectMode="ResponseRewrite" />
like image 141
vvucetic Avatar answered Sep 20 '22 08:09

vvucetic


Apparently, <customErrors> is a mess to get working. If you're determined to use it, Ben Foster has a great write-up on the subject: http://benfoster.io/blog/aspnet-mvc-custom-error-pages

If you want to use .cshtml pages, your best bet is probably to ditch <customErrors> and handle errors in Global.asax.cs:

protected void Application_Error(object sender, EventArgs e)
{
    var exception = Server.GetLastError();
    if (exception != null)
    {
        Response.Clear();
        HttpException httpException = exception as HttpException;
        RouteData routeData = new RouteData();
        routeData.Values.Add("controller", "Error");
        if (httpException == null)
        {
            routeData.Values.Add("action", "Unknown");
        }
        else
        {
            switch (httpException.GetHttpCode())
            {
                case 404:               // Page not found.
                    routeData.Values.Add("action", "NotFound");
                    break;

                default:
                    routeData.Values.Add("action", "Unknown");
                    break;
            }
        }


        // Pass exception details to the target error View.
        routeData.Values.Add("Error", exception);
        // Clear the error on server.
        Server.ClearError();
        // Avoid IIS7 getting in the middle
        Response.TrySkipIisCustomErrors = true;
        // Ensure content-type header is present
        Response.Headers.Add("Content-Type", "text/html");
        // Call target Controller and pass the routeData.
        IController errorController = new ErrorController();
        errorController.Execute(new RequestContext(new HttpContextWrapper(Context), routeData));
    }
}

Of course, you would also need to add an ErrorController with the appropriate methods and .cshtml views.

public class ErrorController : Controller
{
    public ActionResult Index()
    {// your implementation
    }

    public ActionResult Unknown(Exception error)
    {// your implementation 
    }

    public ActionResult NotFound(Exception error)
    {// your implementation         
    }
}
like image 45
Daniel Avatar answered Sep 22 '22 08:09

Daniel