asp.net mvc 4, thread changed by model binding?

486 views Asked by At

I am using a custom ModelBinder in an MVC 4 application, but it is invoked on a different thread than the request event handlers in global.asax, and this makes setting up a performance profiling context in a ThreadLocal fail.

The threadId is in brackets at the start of each line, and you can see that the thread changes when the model binding is invoked, and that is the thread in which the controller action (Index) is executed.

[33] | ERROR | MyApp.MvcApplication | Application_BeginRequest 
[33] | ERROR | MyApp.MvcApplication | Application_AuthenticateRequest
[33] | ERROR | MyApp.MvcApplication | Application_AuthorizeRequest
[33] | ERROR | MyApp.MvcApplication | Application_ResolveRequestCache
[33] | ERROR | MyApp.MvcApplication | Application_AcquireRequestState
[33] | ERROR | MyApp.MvcApplication | Application_PreRequestHandlerExecute
[52] | ERROR | Binders.MyModelBinder | ModelBinder
[52] | ERROR | MyApp.Controllers.MyController | Index

Any idea why this is happening? My expectation was that the controller methods would always be invoked on the same thread as the application event handlers in global.asax

1

There are 1 answers

2
Otto Blorstead On

Turns out that my core assumption was incorrect - the controller actions are not invoked on the same thread as the event handlers.

Here is a snippet from Environment.StackTrace that shows the controller action being invoked by an asynchronous process (on another thread).

at System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.<>c__DisplayClass8.<BeginProcessRequest>b__2(AsyncCallback asyncCallback, Object asyncState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`1.Begin(AsyncCallback callback, Object state, Int32 timeout)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state)
at System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()

Looks like I'll be storing my performance profiling context in the session instead.