ApplicationDbContext getting created/destroyed twice

Feb 24, 2015 at 5:11 PM
Hello,

Followed the steps to get this working with Identity, but after putting a break point in both the constructor and dispose method of my ApplicationDbContext class ... I notice that TWO instances are being created and disposed of.

The first is what is expected.

The second creation/disposal happens AFTER the request has finished executing and the view rendered. Looking at the call stack, it looks as if the startup code is being ran again.

Not sure what is causing this. Here is what my Startup.cs looks like:
[assembly: OwinStartupAttribute(typeof(CustomIdentity.Web.Startup))]
namespace CustomIdentity.Web
{
    public partial class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var container = SimpleInjectorInitializer.Initialize(app);
            ConfigureAuth(app, container);
        }
    }
}
Here is how I'm configuring the ApplicationDbContext in SimpleInjectorInitalizer.cs
container.RegisterPerWebRequest<ApplicationDbContext>(() => new ApplicationDbContext());
Any ideas?

Thanks
Coordinator
Feb 25, 2015 at 10:04 AM
You should set a break point in the constructor and the Dispose method and look at the stack trace what is triggering those calls. If you're in doubt, please post the relevant stack traces here.
Feb 27, 2015 at 8:54 PM
@wgpubs:
I'm able to reporduce your problem. I'm sure it is not coming from Simple Injector.

There are actually no 2 ApplicationDbContexts created, but there are 2 HttpRequests created. Offcourse Simple Injector will create an ApplicationDbContext twice then because it is registered as PerWebRequest.

Currently I'm unsure why this happening. Could be a mistake in the template refactoring from the other thread, but it could also be some very strange default behaviour from MVC, Owin or Identity or the combination of the three.

I'm currently investigating, will do an update when I found something.
Mar 1, 2015 at 9:02 PM
I'm still in the dark why this happens but I'm sure it has nothing to do with Simple Injector and/or the template adjustments described in this thread.

I started a new ASP.Net MVC application and used the default template. I added a static int cnt to the Startup.Auth.cs and changed this:
app.CreatePerOwinContext(ApplicationDbContext.Create);
to this:
    app.CreatePerOwinContext(() =>
            {
                cnt += 1;
                Debug.WriteLine("cnt: " + cnt.ToString());
                Debug.WriteLine(Environment.StackTrace);
                return ApplicationDbContext.Create();
            });
And then simply hit F5. After it was fully loaded I cleared the output window and pushed the login link in the navabar. Here's the output:
cnt: 3
   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at MVC_TEst_New.Startup.<ConfigureAuth>b__2() in c:\MVC TEst New\App_Start\Startup.Auth.cs:line 27
   at Owin.AppBuilderExtensions.<>c__DisplayClass1`1.<CreatePerOwinContext>b__0(IdentityFactoryOptions`1 options, IOwinContext context)
   at Microsoft.AspNet.Identity.Owin.IdentityFactoryProvider`1.Create(IdentityFactoryOptions`1 options, IOwinContext context)
   at Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware`2.<Invoke>d__0.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Start[TStateMachine](TStateMachine& stateMachine)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[TStateMachine](TStateMachine& stateMachine)
   at Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware`2.Invoke(IOwinContext context)
   at Microsoft.Owin.Infrastructure.OwinMiddlewareTransition.Invoke(IDictionary`2 environment)
   at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.BeginEvent(Object sender, EventArgs e, AsyncCallback cb, Object extradata)
   at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
   at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
   at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
   at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
cnt: 4
   at System.Environment.GetStackTrace(Exception e, Boolean needFileInfo)
   at System.Environment.get_StackTrace()
   at MVC_TEst_New.Startup.<ConfigureAuth>b__2() in c:\MVC TEst New\App_Start\Startup.Auth.cs:line 27
   at Owin.AppBuilderExtensions.<>c__DisplayClass1`1.<CreatePerOwinContext>b__0(IdentityFactoryOptions`1 options, IOwinContext context)
   at Microsoft.AspNet.Identity.Owin.IdentityFactoryProvider`1.Create(IdentityFactoryOptions`1 options, IOwinContext context)
   at Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware`2.<Invoke>d__0.MoveNext()
   at System.Runtime.CompilerServices.AsyncMethodBuilderCore.Start[TStateMachine](TStateMachine& stateMachine)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder`1.Start[TStateMachine](TStateMachine& stateMachine)
   at System.Runtime.CompilerServices.AsyncTaskMethodBuilder.Start[TStateMachine](TStateMachine& stateMachine)
   at Microsoft.AspNet.Identity.Owin.IdentityFactoryMiddleware`2.Invoke(IOwinContext context)
   at Microsoft.Owin.Infrastructure.OwinMiddlewareTransition.Invoke(IDictionary`2 environment)
   at Microsoft.Owin.Host.SystemWeb.IntegratedPipeline.IntegratedPipelineContextStage.BeginEvent(Object sender, EventArgs e, AsyncCallback cb, Object extradata)
   at System.Web.HttpApplication.AsyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
   at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
   at System.Web.HttpApplication.PipelineStepManager.ResumeSteps(Exception error)
   at System.Web.HttpApplication.BeginProcessRequestNotification(HttpContext context, AsyncCallback cb)
   at System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotificationHelper(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
   at System.Web.Hosting.PipelineRuntime.ProcessRequestNotification(IntPtr rootedObjectsPointer, IntPtr nativeRequestContext, IntPtr moduleData, Int32 flags)
As you can see, it also hits theApplicationDbContext twice and the stacktrace is identical.

It seems odd to process a request twice. I even tried to built the website to release mode, host it at a 'real' IIS implementation, but the results stay pretty much the same. I checked this because I thought it could be a VS 'bug or feature' which uses all kinds of binding under the covers (like Browser Link and Web Essentials if installed) to let us debug a easy make modifications 'at runtime'.

Where it becomes real strange and questionable is when you test this using Chrome as a browser. Counts go up to 5 requests per click!!

If nobody here understands why this happening we will probably need to ask a question on stackoverflow...
Mar 2, 2015 at 8:13 PM
Yup, I don't get it either. I'm about 99.99% sure it has something to do with the crappy MVC Identity template code.

Anyhow, stripped much of it out in the hopes of building something cleaner, more logical, more DRY and DI friendly here: https://github.com/wgpubs/CustomIdentityWithStructureMap

Check it out. I have a SimpleInjector and StructureMap sample set up (just comment/uncomment the web activator code at the top of these files in App_Start depending on which you want to use.

Thoughts for improvements are most welcomed.


Thanks -wg
Mar 2, 2015 at 9:18 PM
I did research further. It is not coming from Identity. It's coming from Owin. The Owin MIddleware is created a second time after the request ends. I asked a question on StackOverflow about this.

Hopefully somebody there has some good explanation why this is working like this, what it's purpose is and how we should cope with this.

I will take a look at your proposal.
Mar 2, 2015 at 9:46 PM
I'm feeling stupid and not completely convinced at the same time. The answer is: BrowserLink.

When you disable BrowserLink the ApplicationDbContext is indeed created only once.

In the meantime it could still be created a second time when a requests comes for FavIcon or some other resource the browser needs. Which seems to be normal, because it could be a resource which needs authentication.

So the answer is too simple.... Stupid Owin...