I use OWIN + Microsoft.AspNet.Identity.Owin (v.2.0.0.0) in Web application. I register UserManager/DbContext per web request, as widely recommended:
app.Crea
The memory leak in AppBuilderExtensions
class has been already fixed in latest version of Microsoft.AspNet.Identity.Owin
library (2.2.1).
I have checked the code by using Reflector and also by putting a breakpoint into Dispose()
methods of objects created by AppBuilderExtensions.CreatePerOwinContext()
.
I also have his issue, nothing that is registered with CreatePerOwinContext gets disposed. I'm using v2.1.
Here's a temporary fix which is working well for me as a work around until this lib is fixed. You basically have to manually register each of the types that use register with CreatePerOwnContext in the following class, and then at the end of your Startup procedure you register this custom class:
public sealed class OwinContextDisposal : IDisposable
{
private readonly List<IDisposable> _disposables = new List<IDisposable>();
public OwinContextDisposal(IOwinContext owinContext)
{
if (HttpContext.Current == null) return;
//TODO: Add all owin context disposable types here
_disposables.Add(owinContext.Get<MyObject1>());
_disposables.Add(owinContext.Get<MyObject2>());
HttpContext.Current.DisposeOnPipelineCompleted(this);
}
public void Dispose()
{
foreach (var disposable in _disposables)
{
disposable.Dispose();
}
}
}
At the end up your Startup process register this class:
app.CreatePerOwinContext<OwinContextDisposal>(
(o, c) => new OwinContextDisposal(c));
Now everything will get disposed of at the end of the request pipeline properly.
Usage : app.CreatePerRequest<AuthorizationContext>();
Extension Method :
public static IAppBuilder CreatePerRequest<T>(this IAppBuilder builder )where T:IDisposable
{
builder.Use(async (context, next) =>
{
var resolver = context.Get<IDependencyScope>();
using (var instance = (T) resolver.GetService(typeof (T)))
{
context.Set<T>(instance);
if (next != null)
{
await next();
}
}
});
return builder;
}
To Use Dependency Injection you have to configure owin : app.UseScopePerOwinRequest(_dependencyResolver);
- This should be first middleware..
public static IAppBuilder UseScopePerOwinRequest(this IAppBuilder builder,IDependencyResolver resolver)
{
builder.Use(async (context, next) =>
{
using (var instance = resolver.BeginScope())
{
context.Set<IDependencyScope>(instance);
if (next != null)
{
await next();
}
}
});
return builder;
}
And for above code to work you have to implement IDepedencyResolver with any container.
You can put the logic for disposing the instances you create with CreatePeOwinContext()
in the same callback you use to create this intances.
That is:
public class Startup
{
public void Configuration(IAppBuilder app)
{
app.CreatePerOwinContext<ClassIWantOneInstancePerContext>(ClassIWantOneInstancePerContext.Create);
//other code...
}
}
Then you only should care about to include a call to DisposeOnPipelineCompleted()
within the callback used to instantiate your class. That is:
public class ClassIWantOneInstancePerContext
{
//other code...
public static ClassIWantOneInstancePerContext Create()
{
ClassIWantOneInstancePerContext TheInstance = new ClassIWantOneInstancePerContext();
HttpContext.Current.DisposeOnPipelineCompleted(TheInstance);
return TheInstance;
}
}
Also don't forget to include the Dispose()
method on your class definition!