Ultimate Guide To Installing Elmah Within Umbraco

If you haven't come across ELMAH yet, then you should definitely do some research on it.  Elmah provides a nice UI so you can view your server errors from a web page rather than needing to log onto your server and looking within your App_Data folder.  Out of the box, Elmah is designed to work with MVC< however, if you're using Umbraco I'm sure you'll want to view it from within the Umbraco backend, and lock the portal down so only logged in Umbraco admins can view the errors.  The best part of Elmah is that like Umbraco, it's free.  If you want to learn how to implement this cool feature within your website, then read on.

How To Install Elmah With Umbraco

Like all things.NET we install Elmah via Nuget, right click on your website in Visual Studio -> Manage NuGet Packages and search for Elmah:

As you can see, you're in good company using Elmah as over 2.5 million people have installed it.  Now Elmah was originally designed to work with web forms.  If everything goes to plan, you should see a few new entries in your web.config.  Now, I'm assuming you're using MVC and Umbraco if you're not... and at certain companies, you can't... I feel your pain.

Now, if you type in www.website.com/elmah.asx, you should be able to see the Elmah portal.  It is pretty easy to get Elmah up and running, however, the URL isn't secure and anyone can view it, the URL is a web forms URL... YUK. Finally, you can't access it via the Umbraco backend.  Let's sort that out.

How To Configure Elmah With Umbraco

First, to get rid of the web forms URL, we need to remove the following sections from your web.config:

<system.web>

        <!--<httpHandlers>
            <add verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
        </httpHandlers>-->

    </system.web>

<system.webServer>

    <!--<handlers>
    <remove name="Wild" />
    <add name="Elmah" verb="POST,GET,HEAD" path="elmah.axd" type="Elmah.ErrorLogPageFactory, Elmah" />
    </handlers>-->

</system.webServer>

Or if a pretty picture helps:

and:

Next, we need to create an MVC controller so we can load the portal up and lock the portal down.

    public class ElmahController : UmbracoAuthorizedController
    {
        public ActionResult Index(string type)
        {
            return new ElmahResult(type);
        }
    }

Let's quickly re-cap the code. We inherit from 'UmbracoAuthorizedController'. This is the bit that will lock our view/the Elmah portal down to authorized Umbraco users. Next, we use a custom class ElmahResult to return the Elmah portal. That code looks like this:

     public class ElmahResult : ActionResult 
{ private string _resouceType; public ElmahResult(string resouceType)
{ _resouceType = resouceType; } public override void ExecuteResult(ControllerContext context)
{ var factory = new Elmah.ErrorLogPageFactory(); if (!string.IsNullOrEmpty(_resouceType))
{ var pathInfo = "/" + _resouceType; context.HttpContext.RewritePath(FilePath(context), pathInfo, context.HttpContext.Request.QueryString.ToString()); } var currentApplication = (HttpApplication)context.HttpContext.GetService(typeof(HttpApplication)); var currentContext = currentApplication.Context; var httpHandler = factory.GetHandler(currentContext, null, null, null); if (httpHandler is IHttpAsyncHandler)
{ var asyncHttpHandler = (IHttpAsyncHandler)httpHandler; asyncHttpHandler.BeginProcessRequest(currentContext, (r) => { }, null); } else
{ httpHandler.ProcessRequest(currentContext); } } private string FilePath(ControllerContext context) { return _resouceType != "stylesheet" ? context.HttpContext.Request.Path.Replace(String.Format("/{0}", _resouceType), string.Empty) : context.HttpContext.Request.Path; } }

I'll hold my hands up that I found this code on the web, but, it works, so why re-invent the wheel. Next, we need to define a new route (think URL) for us to access the Elmah portal. I always use a separate RouteConfig.cs to store my custom route in my project, otherwise, you can use the global.ascx. If that statement confuses you, I'd recommend giving it a quick google. This stuff is basic MVC stuff so you don't need to panic. My Elmah route looks like this:

            RouteTable.Routes.MapRoute(
               "Elmah",
               "umbraco/backoffice/Plugins/elmah/{type}",
               new
               {
                   controller = "Elmah",
                   action = "Index",
                   type = UrlParameter.Optional
               });

Now if you run your website, you should be able to use this URL www.website.com/umbraco/backoffice/Plugins/elmah and the Elmah portal should load:

 

 

So far we've got an MVC friendly URL that only logged in Umbraco users can access.  The last part is to make the portal accessible from the Umbraco backend.  I've covered how to do this before in, How To Display An MVC In The Umbraco Backend.  So I'll cover the code here. First, we need to create a new section:

 
    [Application("admin", "Admin", "icon-people", 15)]
    public class AdminSection : umbraco.interfaces.IApplication
    {
    }

Next, we create a tree node:

 
   [ Tree("admin", "adminTree", "Admin")]
    public class AdminTree : BaseTree
    {
        public AdminTree(string application)
            : base(application)
        {
        }

        protected override void CreateRootNode(ref XmlTreeNode rootNode)
        {
            rootNode.NodeType = "example";
            rootNode.NodeID = "init";
            rootNode.Menu = new List { ActionRefresh.Instance };
        }

        public override void Render(ref XmlTree tree)
        {
            var elmahNode = XmlTreeNode.Create(this);
            elmahNode.NodeID = "6";
            elmahNode.NodeType = string.Empty;
            elmahNode.Text = "Elmah";
            elmahNode.Action = "#";
            elmahNode.Action = "javascript:openPage('/umbraco/backoffice/Plugins/elmah/{type}');";
            elmahNode.Icon = "../../../App_Plugins/sass-icon-grey.png";
            elmahNode.HasChildren = false;
            elmahNode.Menu = new List();
            OnBeforeNodeRender(ref tree, ref elmahNode, EventArgs.Empty);
            tree.Add(elmahNode);
            OnAfterNodeRender(ref tree, ref elmahNode, EventArgs.Empty);
        }

        public override void RenderJS(ref StringBuilder Javascript)
        {
            var adminJs = $"function openPage(url){{UmbClientMgr.contentFrame(url);}}";
            
            Javascript.Append(adminJs);
        }
    }

Now, if everything has gone to plan when you load your Umbraco backend, you should see something similar to this:

 

Umbraco, Elmah and Azure

Everything above works great as long as you can log onto the server and run the Umbraco back office. If you're running Umbraco within a web app within Azure, for example, you won't be able to do this. If you find yourself in this situation, in your web.config, if you find the Elmah section, change the allowRemoteAccess setting to true. <security allowRemoteAccess="true" />

Elmah Umbraco Takeaway

Elmah is a pretty useful package that I recommend you install within your website.  To get Elmah to work with Umbraco, you will have to jump through a few more hoops than a normal Umbraco website, but, if you follow the steps correctly then the extra work should only take an extra 10-15 minutes.  Enjoy!

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

Back to top