Using MiniProfiler with a hybrid asp.net Web Forms / MVC application - Part 1

If you've got an application, like we have, that uses asp.net Web Forms for the UI components and MVC (5) for the endpoints that are used by JavaScript to retrieve/save data, it's still posible to take advantage of MiniProfiler, it's just a little bit "twisty" to get it all wired up right.

The first step is to install the required packages into your project, using the NuGet package manager. Via the console, or via the GUI, the two packages you're looking for are:

  • MiniProfiler.Mvc4
  • MiniProfiler

Pulling in MiniProfiler.Mvc4 should automatically resuilt in the presence of MiniProfiler, so you'll only need to add one of them, so via the NuGet console the command:

Install-Package MiniProfiler.Mvc4

There is a package for "MiniProfiler.Mvc5" but it's in alpha/pre-release at the moment and the Mvc4 package seems to do the job for now.

Getting the MiniProfiler UI to show in the web forms components

The starting project I've used for this is (using Visual Studio 2017) created by choosing File > New > Project > ASP.NET Web Application (.NET Framework), then choosing "Web Forms" from the Templates options and also ticking "MVC" for the "Add folders and core references for" options. Once that was done, I added the MiniProfiler.Mvc4 package and then made the following changes:

Added handlers for Application_BeginRequest and Application_EndRequest in Global.asax:

protected void Application_BeginRequest()
{
    MiniProfiler.Start();
}
protected void Application_EndRequest()
{
    MiniProfiler.Stop();
}

Adding these required adding a "using StackExchange.Profiling" to bring Miniprofiler into scope.

The next step is to add the scripts and other includes into the output Web Forms pages by modifying the Site.Master page that is automatically added as part of this template, to add the following bit of code to the <head> of the page:

<asp:ContentPlaceHolder ID="MiniProfilerContentPlaceholder" runat="server">
    <%= StackExchange.Profiling.MiniProfiler.RenderIncludes(showControls: true, startHidden: false, showTimeWithChildren: true, position: StackExchange.Profiling.RenderPosition.Right) %>
    <%= StackExchange.Profiling.ClientTimingHelper.InitScript %>
</asp:ContentPlaceHolder>

I've placed this in a ContentPlaceHolder just in-case I need to override the behaviours at some point in another page (e.g. if I have a page where the (top) right-hand side of the page contains information that I need to see

The last step is to add the MiniProfiler handler to the configuration > system.webServer > handlers section of the web.config file for the project so that the script/css references that are generated by the code added to the master page return the code required for MiniProfiler to run:

<add name="MiniProfiler" path="mini-profiler-resources/*" verb="*" type="System.Web.Routing.UrlRoutingModule" resourceType="Unspecified" preCondition="integratedMode" />

Hitting F5 and viewing the resultant page will show the MiniProfiler UI in the top right-hand corner of the page. You can click on the entries in the UI (each of them showing the number of milliseconds that request took to execute) and see what the components of that are. Just now I ran my project and default.aspx took 1977.7ms to execute, with MiniProfiler showing me how long each of various client-side actions took to execute, along with how long the page itself took to generate.

Adding a profiling action to the Web Forms page

To show how easy it is to add MiniProfiler to a page, I added the following code to Default.aspx.cs:

protected void Page_Load(object sender, EventArgs e)
{
    using (var profile = MiniProfiler.Current.Step("Page_Load"))
    {
        System.Threading.Thread.Sleep(500);
    }
}

This causes MiniProfiler to time how long the actions inside the using take, and then report them with the identifier "Page_Load". I've used a simple Thread.Sleep to emulate actually doing some work. When the page is now loaded, the information for the server-side events will be broken out to show how long the action named "Page_Load" took to execute:

This means that we can now profile any event that occurs in the Web Forms page(s) within the site, leaving the next step to be wiring this into the MVC Controllers so that MiniProfiler also reports on the actions that take place there.

About Rob

I've been interested in computing since the day my Dad purchased his first business PC (an Amstrad PC 1640 for anyone interested) which introduced me to MS-DOS batch programming and BASIC.

My skillset has matured somewhat since then, which you'll probably see from the posts here. You can read a bit more about me on the about page of the site, or check out some of the other posts on my areas of interest.

No Comments

Add a Comment