ELMAH (Error Logging Modules and Handlers) is a great framework for error logging in your ASP.NET application. It just works – out of the box. Best of all, it is on Nuget – so you can just add the nuget package and you have immediate error logging for all unhandled exceptions. ELMAH is open-source so you can check out the implementations of Elmah and Elmah.Mvc online.

This is ELMAH using the default setup.

s1.png

Let’s start customizing ELMAH. First, we’ll look at the default values for ELMAH.

s2.png

ELMAH.MVC has support for role-based security as you can see in the settings above. So what if you aren’t doing role-based security? Let’s look into one way to get around it.

First, let’s change the web.config. Change the setting for “elmah.mvc.IgnoreDefaultRoute” to true. This is necessary for us to re-route the traffic.

Next, would be to implement your custom security attribute. Here is an example of one that I am using.

using System.Web.Mvc;

public class CustomAuthorizeAttribute : AuthorizeAttribute
{
public CustomAuthorizeAttribute(Component component)
{
this.Component = component;
}

protected override bool AuthorizeCore(
HttpContextBase httpContext)
{
if (Component == null)
return SecurityHelper.CurrentUser != null;
else
return SecurityHelper.Can(Component.Value);
}

protected override void HandleUnauthorizedRequest(
AuthorizationContext filterContext)
{
filterContext.Result =
new RedirectToRouteResult(
new RouteValueDictionary(
new { controller = "Error",
action = "Unauthorized" }));
}


public Component? Component { get; set; }
}

Component is just an Enum with the security access. Now that we have our custom security attribute, we can create a controller for our new route.

[CustomAuthorize(Component.Admin)]
public class ErrorLogController : Elmah.Mvc.ElmahController
{

}

I do not need any actions in it because I will just be using the ones from the base class. If we run the app, we see that we can now access ELMAH and it uses our custom security attribute. However, there seems to be a problem.

s3.png

We do not have any styling. The reason for this (as you might be able to tell from the errors at the top of ELMAH) is because ELMAH looks for the stylesheet relative to what ELMAH’s controller name is. We made our own so it is looking in the new path. We can verify this by opening up our dev tools.

s4.png

Note: if you use don’t use a custom controller and change the web.config setting “elmah.mvc.route” to “errorlog” then the styling can be found because elmah handles the rewriting for you.

To fix this, we need to make some additional changes to our MVC app. First, we need to get a valid stylesheet. Navigate back to the working ELMAH (you may need to change the web.config setting) and let the valid page load. Now, open your browser dev tools and copy the css from “stylesheet”. Create a new css file (where ever you prefer) in your Content folder in your project and paste the css into it. You can also tweak the styles to match your site if you wish. In the “App_Start” folder, open the BundleConfig. We can now add a bundle for our stylesheet.

bundles.Add(new StyleBundle("~/errorlog/stylesheet")
.Include("~/Content/themes/elmah/elmah.css")
);

We now have a virtual path to the missing stylesheet. Running the app and navigating back to /ErrorLog shows us the ELMAH logs with the styling and using our security attribute.

You will still need to have “allowRemoteAccess=1” in the web.config; otherwise, you won’t be able to access your new controller.

Extra points: You have made all of these changes but you say to yourself: “self, everyone is used to going to /Elmah and I don’t want to have to change paths or tell them to go to my new custom controller”. Good news! We can get around that.

In the web.config, change the “elmah.mvc.route” to any path that isn’t currently being used. This will be the path to the default/non-customizedELMAH. I just set it to “_” (underscore). FYI, if you have your path set to /Elmah and you don’t change the default route, then the out-of-the-boxELMAH will win. Now we just need to create a custom route. Go back to “App_Start” and open the RouteConfig. Let’s add a new route for our controller.

routes.MapRoute(
name: "Admin_elmah",
url: "elmah/{type}",
defaults: new
{
action = "Index",
controller = "ErrorLog",
type = UrlParameter.Optional
},
namespaces: new[] { "MyApp.UI.Controllers" }
);

Make sure that you put this ABOVE your default MVC route otherwise it will not do anything. Now just change the namespace to your namespace and navigating to /Elmah will use the custom one. If by chance you wanted to name your controller ElmahController instead of ErrorLogController, that will work too! Just change the controller property to “Elmah” and at the very top of the routes, call “routes.Clear()”. Elmah.Mvc is creating and overwriting some routes in the nuget packages and if you don’t clear them then you will have some issues if you try to name your controller ElmahController.

To sum it up, the quick steps are:

  1. Add nuget packages 

  2. Edit web.config 

  3. Create security attribute 

  4. Create new controller 

  5. Copy default css and include in project 

  6. Update the bundleconfig 

  7. Update the routeconfig

Hopefully this can help you if you were having this issue or at the least point you in the right direction to figuring it out in your specific case.

Is this interesting, want to learn more, or are having the same discussions in your own department? Get in touch with us so we can discuss how we can help your business achieve its goals through leadership and technology.


Information and material in our blog posts are provided "as is" with no warranties either expressed or implied. Each post is an individual expression of our Sparkies. Should you identify any such content that is harmful, malicious, sensitive or unnecessary, please contact  marketing@sparkhound.com

Get Email Notifications