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 in HttpContext.Current
MessageHandler, I can see HttpContext.Current
IActionFilter, HttpContext.Current is now null, and my attempt to MiniProfiler.Current.Step("controller:action") failsMiniProfiler.Current, which relies on HttpContext.Current, which is null right nowApplication_EndRequest fires, and HttpContext.Current is magically back, and so it wraps up the profiler and tells me how long it's been since the request beganI 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:
IProfileProvider is a global variable; all worker threads in either the MVC or Web API pipeline all have to use the same IProfileProvider
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 profileInRequestScope because InRequestScope doesn't seem to work with web api 2.1, but even if I couldHttpRequestMessage.Properties is the new HttpContext.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 version HttpRequestMessage. MiniProfiler.Current can be called from anywhere, so I guess a global IProfileProvider would have to somehow inspect the call stack to and find an HttpRequestMessage there? That sounds like madness.I'm at a loss. What I really want is a special variable.
The process of putting the question together I figured it out. HttpContext.Current can get lost when you async/await things: Why is HttpContext.Current null after await?
I had to make the web.config change listed there, and adjusted my filters to use Miniprofiler.Current before any awaiting.
Also discussed at https://www.trycatchfail.com/2014/04/25/using-httpcontext-safely-after-async-in-asp-net-mvc-applications/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With