I have a question about creating a temporary request scope when using the Web API OWIN pipeline with Autofac.
We have the need to disable some external dependencies on demand so our QA team can test their negative test cases. I did not want to change ANY code in the normal application flow, so what I did was create a custom middleware that inspects a request for certain QA headers, and when they are present extends the normal container with a temporary new scope, registers a replacement object only for that call, overrides the autofac:OwinLifetimeScope, then disposes that temporary scope at the end of that call.
This has allowed me to override the normal container behaviour for that request only, but allow all other requests to continue as normal.
Here is a modified sample of my middleware. This code is working fully as expected.
public override async Task Invoke(IOwinContext context)
{
var headerKey = ConfigurationManager.AppSettings["QaTest.OfflineVendors.HeaderKey"];
if (headerKey != null && context.Request.Headers.ContainsKey(headerKey))
{
var offlineVendorString = context.Request.Headers[headerKey].ToUpper(); //list of stuff to blow up
Action<ContainerBuilder> qaRegistration = builder =>
{
if (offlineVendorString.Contains("OTHERAPI"))
{
var otherClient = new Mock<IOtherClient>();
otherClient.Setup(x => x.GetValue()).Throws<APIServiceUnavailableException>();
builder.Register(c => otherClient.Object).As<IOtherClient>();
}
};
using (
var scope =
context.GetAutofacLifetimeScope()
.BeginLifetimeScope(MatchingScopeLifetimeTags.RequestLifetimeScopeTag, qaRegistration))
{
var key = context.Environment.Keys.First(s => s.StartsWith("autofac:OwinLifetimeScope"));
context.Set(key, scope);
await this.Next.Invoke(context).ConfigureAwait(false);
}
}
else
{
await this.Next.Invoke(context).ConfigureAwait(false);
}
}
However, the lines
var key = context.Environment.Keys.First(s => s.StartsWith("autofac:OwinLifetimeScope"));
context.Set(key, scope);
seem very hacky and I don't like them. I have searched all around, but I have not found a way to cleanly override the context object, or found a better way to implement this functionality.
I'm looking for any suggestions for a better way to handle this.