Problem: You are developing/maintaining an ASP.NET web-site, and would like the ability to conditionally show/hide runtime error messages depending on who the user visiting the site is.
For a normal user visiting the site you want to be able to display a friendly error message like this when a runtime error occurs:
But when someone within the “developers” security role of your application remotely accesses the site you want to instead show a more detailed exception stack trace error message about the problem without having to change any configuration data:
The below post describes how to use ASP.NET’s role-based security architecture in conjunction with the Global.asax Application_Error event handler to enable this. You can also download a sample I’ve built that shows how to implement this here.
Some Background Discussion on Error Handling and ASP.NET Custom Error Pages:
ASP.NET and .NET support a rich error-handling architecture that provides a flexible way to catch/handle errors at multiple levels within an application. Specifically, you can catch and handle a runtime exception with a class, within a page, or on the global application level using the Application_Error event handler within the Global.asax class. If a runtime exception isn’t handled/cancelled by one of these mechanisms, then ASP.NET’s Custom Error Page feature will kick-in, and an error page will be sent back to the browser accessing the application.
ASP.NET’s Custom Error Page feature can be used to configure a “friendly error page” to be displayed to end-users in place of the standard “server error occurred” message sent back by ASP.NET. For example, the below web.config file section will cause remote users visiting the site to be redirected to a “friendlyErrorPage.htm” file anytime a runtime error occurs (note: HTTP 500 status code responses indicate runtime errors on the server):
<error statusCode="500" redirect="friendlyErrorPage.htm"/>
To learn more about how the ASP.NET Custom Errors feature works, and how to configure it, please review this article.
Important: I would recommend never setting the <customErrors> mode attribute to “Off”. Doing this will cause detailed error messages to be sent back to all normal users visiting your site. This can lead to information disclosure issues that can compromise the security of your site. Instead, only change this setting to “On” or “RemoteOnly” (the default) and use the technique below for cases where you want to display detailed error messages to only some users.
The above <customErrors> configuration section will cause a friendly error message to be sent to the browser anytime a runtime error message occurs. This is what we want to happen anytime a normal user access the site, and will allow us to display error pages like this:
To enable developers to instead see detailed error messages when they access the site, I can then add this code to the Application_Error event handler within the Global.asax class:
Sub Application_Error(ByVal sender As Object, ByVal e As EventArgs)
If (Context IsNot Nothing) And (Context.User.IsInRole("Developer")) Then
Dim err As Exception = Server.GetLastError()
Response.Write("<h1>" & err.InnerException.Message & "</h1>")
Response.Write("<pre>" & err.ToString & "</pre>")
The above code checks to see if the current user visiting the site is within a specific security role. If so, then it retrieves the exception raised during the current request via the Server.GetLastError() method. It then clears out any content already generated during the current request, and instead outputs the Exception details to the response. Lastly, it clears out the Exception from the request – which will prevent ASP.NET’s custom error architecture from kicking in. The result instead is a page that details the error like so:
To learn more about how you can easily create and manage a “Developer” role like the one I’m using above, please review my previous post: Implementing Role Based Security with ASP.NET using Windows Authentication and SQL Server. If you don’t want to store your role-mappings within a database, you can also store them within Active Directory or your own custom role-provider.
This sample demonstrates using a Windows User’s membership within the local “Administrators” group on a machine to control whether or not the detailed error message is displayed. Note: you can perform a role-check on a local Windows group by writing: User.IsInRole(“BUILTIN\Administrators”) – where the “BUILTIN” prefix indicates that it is a local group as opposed to a domain level one).
Hope this helps,
P.S. Please visit this page to read more articles within my “ASP.NET 2.0 Tips/Tricks/Recipes and Gotchas” series.