I'm trying to setup MiniProfiler on my web api site, and having a hard time getting MiniProfiler.Current
to work.
I followed the directions at miniprofiler.com, and have the following in global.asax:
protected void Application_Start()
{
MiniProfilerEF6.Initialize();
// other setup
}
protected void Application_BeginRequest() {
// need to start one here in order to render out the UI
MiniProfiler.Start();
}
protected void Application_EndRequest() {
MiniProfiler.Stop();
}
This uses the default WebRequestProfilerProvider, which stores the actual profile object in HttpContext.Current.Items
.
When I ask for MiniProfiler.Current
, it looks to HttpContext.Current
.
When I make a request for one of my web api URLs:
Application_BeginRequest
creates the profiler, store it inHttpContext.Current
- in a web api
MessageHandler
, I can seeHttpContext.Current
- in a web apu
IActionFilter
,HttpContext.Current
is now null, and my attempt toMiniProfiler.Current.Step("controller:action")
fails - my EF queries run from various services do not get recorded, as that miniprofiler hook relies
MiniProfiler.Current
, which relies onHttpContext.Current
, which is null right now Application_EndRequest
fires, andHttpContext.Current
is magically back, and so it wraps up the profiler and tells me how long it's been since the request began
I dug through the code, and I can create my own IProfileProvider
, to store the profiler object somewhere more reliable than HttpContext.Current
, but I don't know where that could be.
I spent a few hours trying things out, but couldn't find a workable solution. The problems:
- the
IProfileProvider
is a global variable; all worker threads in either the MVC or Web API pipeline all have to use the sameIProfileProvider
- I can dig around in web api RequestContext.Properties to pull out the HttpContext for that request, but that doesn't really help because my
IProfileProvider
is global across the entire app; If I tell it to store the profile in HttpContext A, then any simultaneous requests for other HttpContexts are going to pollute the profile - I can't rely on any kind of threadstorage because of async/await re-using threads dynamically
- I can't stick the profiler object in an Ninject binding with
InRequestScope
becauseInRequestScope
doesn't seem to work with web api 2.1, but even if I could - everyone says
HttpRequestMessage.Properties
is the newHttpContext.Current.Items
, but again,IProfileProvider
is a global variable and I don't know of a way to ensure each request is looking at their versionHttpRequestMessage
.MiniProfiler.Current
can be called from anywhere, so I guess a globalIProfileProvider
would have to somehow inspect the call stack to and find anHttpRequestMessage
there? That sounds like madness.
I'm at a loss. What I really want is a special variable.