Skip to content

Instantly share code, notes, and snippets.

@timw255
Last active August 29, 2015 14:14
Show Gist options
  • Save timw255/f0c10de9be1dcb98b0d6 to your computer and use it in GitHub Desktop.
Save timw255/f0c10de9be1dcb98b0d6 to your computer and use it in GitHub Desktop.
Custom Errors Module - Proof of Concept
protected void Application_Error(object sender, EventArgs e)
{
// check to see if something horrible is going on...
if (Request.Headers["Custom-Error-Request"] != null)
{
// looks like a request to grab an error page ended up here. let's bail.
return;
}
// get the last error
HttpException err = Server.GetLastError() as HttpException;
Server.ClearError();
// try to skip using any other custom error settings
Response.TrySkipIisCustomErrors = true;
// check to see if we need to send back something pretty
var acceptsHtml = Request.Headers["Accept"].Contains("text/html");
// we're on!
if (err != null && acceptsHtml)
{
// get the language from the visitor's browser settings
string lang = (Request.UserLanguages ?? Enumerable.Empty<string>()).FirstOrDefault();
var culture = CultureInfo.GetCultureInfo(lang);
// set the culture to match the browser language
Thread.CurrentThread.CurrentUICulture = culture;
PageManager pageManager = PageManager.GetManager();
PageNode pNode = null;
// this is where we would put a manager to do some fancy lookups based on the error codes
switch (err.GetHttpCode())
{
case 404:
pNode = pageManager.GetPageNodes().Where(pN => pN.Title == "404").FirstOrDefault();
break;
case 500:
default:
pNode = pageManager.GetPageNodes().Where(pN => pN.Title == "Generic").FirstOrDefault();
break;
}
// grab the URL of the error page we're going to display to the visitor
string url = pNode.GetFullUrl(culture, true);
url = UrlPath.ResolveUrl(url, true, true);
// grab the entire HTML of the page
WebClient client = new WebClient { Encoding = Encoding.UTF8 };
client.Headers.Add("Custom-Error-Request", "");
string html = err.GetHttpCode().ToString();
try
{
html = client.DownloadString(url);
}
catch (WebException ex)
{
// the error page is probably blowing up. maybe do some logging...or send an email?
}
// send back the the best response we got for the error and a status code
Response.Write(html);
Response.StatusCode = err.GetHttpCode();
}
else if (err != null)
{
// just fire back a basic message and the status
Response.Write(err.GetHttpCode().ToString());
Response.StatusCode = err.GetHttpCode();
}
}
<customErrors mode="On">
<error statusCode="404" redirect="~/8ec96125-02ce-47e2-a545-0eba4192dc7d" />
</customErrors>
<httpErrors errorMode="Custom">
<remove statusCode="404" subStatusCode="-1" />
<error statusCode="404" prefixLanguageFilePath="" path="/CustomErrorPages/8ec96125-02ce-47e2-a545-0eba4192dc7d.aspx" responseMode="ExecuteURL" />
</httpErrors>
@timw255
Copy link
Author

timw255 commented Feb 2, 2015

I hadn't thought about the accept header thing, good call.

The language sniffing was done because I want to grab the page and return it under the same URL, along with the error code. Because I'm not doing a redirect (spinning up the WebRequest manually) I didn't think I could rely on Sitefinity to return the correct page. I admit that I might be over-complicating it though. 😄

If WebClient is faster and returns the same result, I'm totally making the switch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment