Using MiniProfiler with EPiServer CMS7

U

MiniProfiler is a great tool for allowing in-situ profiling to be performed directly on a production site; by your development team whilst hiding any detailed specific information from a standard end user. It was developed by Sam Saffron who built it (and then open sourced it) to solve real-world profiling issues on StackOverflow.

It’s been around for a while and has already been integrated with EPiServer 6 based sites. However it really comes into its own when you can hook it into application events that contain performance information that you really care about. MiniProfiler already comes with some integration good hooks into the MVC framework allowing you to profile each of your controller action methods, and also some useful hooks into EntityFramework which allow to to see and time any database calls that EF makes for you.

The underlying API improvements in EPiServer CMS 7 allow us to easily integrate the new shinier ASP.NET tools and gain some real value from them. In the case of MiniProfiler – we can use the new EPiServer IContentRepository interface (whose usage replaces the DataFactory singleton) to build a concrete implementation which wraps the standard implementation to provide hooks into MiniProfiler. This means we can easily see what data related calls our EPiServer templates make on screen as the page is delivered. This is a great tool for assessing page performance and cache usage.

POSSIBLE.ProfiledContentRepository

I’ve released a Nuget package that contains 95% of the code you need to see meaningful MiniProfiler output on your CMS7 site.

  • ProfiledContentRepository – an IContentRepository implementation contains MiniProfiler steps. An example of the GetChildren<T> IContentRepository method is shown below.
public IEnumerable<T> GetChildren<T>(ContentReference contentLink) where T : IContentData
{
    string stepName = string.Format("GetChildren<{0}>[{1}]", typeof(T).Name, contentLink);

    using (MiniProfiler.Current.Step(stepName))
    {
        return DataFactory.Instance.GetChildren<T>(contentLink);
    }
}
  • Container initialisation – the ProfiledContentRepository¬† instance is injected into the EPiServer IoC container via an Initialisation module and then used as the default implementation for all content retrieval
  • Global application event hooks – MiniProfiler is started and stopped on each Http Request by registering against global application begin and end requests events (performed via the init method of an HttpModule).
  • Overridable display logic – You can choose any arbitrary logic to decide how and whether to show the MiniProfiler output to a site visitor. Usually you’d do this via the incoming request IP address or by checking for the presence of a specific Http header. By default the Nuget package will show the output to any Http request from an authenticated user matching the WebAdmin / Administrator roles. This behaviour can be modified by amending the¬†DisplayProfilerHandler.ShouldShow and the DisplayProfileHandler.ShowToUser delegates which you’d likely do on application start up or in an initialisation module. As an example – the following will set the module to only display to me (username mark.everard) when I’m visiting from a specific IP address.
DisplayProfilerHandler.ShouldStart= httpContext => httpContext.Request.ServerVariables["REMOTE_ADDR"].Equals("217.114.90.249");

DisplayProfilerHandler.ShowToUser= httpContext => httpContext.User.Identity.Name == "mark.everard;

Ideally you want to start profiling early and only for users that will see the end information. This is the reason for the multiple delegates where you can set your behaviour as to whether to start profiling (which happens on the global BeginRequest event – that occurs before ASP.NET has worked out whether the request is from an authenticated user) and also on the PostAuthorizeRequest method that works out whether to continue profiling and can contain user specific logic. This is mentioned in more detail in this Stack Overflow post.

For optimum performance when using this module in production you should override the default DisplayProfilerHandler.ShouldStart delegate. By default every request is profiled, and then the results thrown away when we can calculate whether the user is logged into EPiServer.

Installation

To use this – install the POSSIBLE.ProfiledContentRepository package from the EPiServer Nuget feed and remember that you need to add the following line to your MasterPage / Layout file just before the closing body tag. It is this call that actually outputs the profiling information.

@MiniProfiler.RenderIncludes();

miniprofiler-example

Happy Profiling!!

About the author

Mark Everard

I've worked across the digital industry for the past ten years, helping clients and colleagues across a diverse range of sectors meet numerous digital challenges, specifically focusing on web technologies, digital marketing and content management.

I've worked on large multi-supplier projects and led and managed both in-house and geographically-disperse development teams. And I've always approached my work with a smile on my face.

Mark Everard

I've worked across the digital industry for the past ten years, helping clients and colleagues across a diverse range of sectors meet numerous digital challenges, specifically focusing on web technologies, digital marketing and content management.

I've worked on large multi-supplier projects and led and managed both in-house and geographically-disperse development teams. And I've always approached my work with a smile on my face.

Get in touch