I am working on self-hosted web api using OWIN and I need to register a service per scope lifestyle using Castle Windsor.
I know that using HttpContext I can achieve that using PerWebRequest or HybridPerWebRequestPerThread lifestyle but in my case I don't have HttpContext.
I have created the following owin middleware which will be the first and the last middleware will be executed during the request :
public class SetupMiddleware : OwinMiddleware
{
public SetupMiddleware(OwinMiddleware next) : base(next)
{
if (next == null)
{
throw new ArgumentNullException("next");
}
}
public override async Task Invoke(IOwinContext context)
{
IDisposable scope = null;
try
{
//here I am starting new scope
var container= IoCResolverFactory.GetContainer();
scope = container.BeginScope();
await Next.Invoke(context);
}
catch (Exception ex)
{
}
finally
{
//here I am disposing it
scope?.Dispose();
}
}
And when I Startup my application I register my service inside the IoC container as following:
container.BeginScope();
container.Register(Component.For<ICurrentRequestService>().ImplementedBy<CurrentRequestService>().LifestyleScoped());
The problem when I resolve instance of CurrentRequestService, it does not work as per scope which owin middleware will begin it when a new request comes and dispose it when it finishes.
Could you please guide me to how can I register services per scope to behave like PerWebRequest in my application?
As I expected that I should define a custom scope to be started and dispose within a middleware .
I have created the following custom scope accessor:
public class OwinWebRequestScopeAccessor : IScopeAccessor
{
void IDisposable.Dispose() { }
ILifetimeScope IScopeAccessor.GetScope(CreationContext context)
{
IOwinContext owinContext = HttpContext.Current.GetOwinContext();
string key = SetupMiddleware.EnvironmentKey;
return owinContext.Environment[key] as ILifetimeScope;
}
}
Then I have modified my SetupMiddleware as followings:
public class SetupMiddleware : OwinMiddleware
{
public const string EnvironmentKey = "WindsorOwinScope";
public SetupMiddleware(OwinMiddleware next) : base(next)
{
if (next == null)
{
throw new ArgumentNullException("next");
}
}
public override async Task Invoke(IOwinContext context)
{
ILifetimeScope lifetimeScope = new DefaultLifetimeScope();
try
{
context.Environment[EnvironmentKey] = lifetimeScope;
await Next.Invoke(context);
}
catch (Exception ex)
{
}
finally
{
context.Environment.Remove(EnvironmentKey);
lifetimeScope.Dispose();
}
}
}
Then I registered my service using the above scope :
container.Register(Component.For<ICurrentRequestService>().ImplementedBy<CurrentRequestService>().LifestyleScoped<OwinWebRequestScopeAccessor>());
PS:
SetupMiddleware should be the first middleware in the owin pipeline.
I hope my code will help others.