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_BeginRequestcreates the profiler, store it inHttpContext.Current- in a web api
MessageHandler, I can seeHttpContext.Current - in a web apu
IActionFilter,HttpContext.Currentis 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_EndRequestfires, andHttpContext.Currentis 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
IProfileProvideris 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
IProfileProvideris 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
InRequestScopebecauseInRequestScopedoesn't seem to work with web api 2.1, but even if I could - everyone says
HttpRequestMessage.Propertiesis the newHttpContext.Current.Items, but again,IProfileProvideris a global variable and I don't know of a way to ensure each request is looking at their versionHttpRequestMessage.MiniProfiler.Currentcan be called from anywhere, so I guess a globalIProfileProviderwould have to somehow inspect the call stack to and find anHttpRequestMessagethere? That sounds like madness.
I'm at a loss. What I really want is a special variable.