ASP.NET MVC 5 + Owin + SimpleInjector - c#

A new asp.net mvc project using owin, webapi, mvc and DI (SimpleInjector) runs fine if I remove the DI lib from the project. However, once introduced, the app blows up when registering the OWIN components for DI. The OWIN startup configuration is being hit and runs without error, but when it comes time to register the dependencies (listed below) I receive the following error:
An exception of type 'System.InvalidOperationException' occurred in Microsoft.Owin.Host.SystemWeb.dll but was not handled in user code
Additional information: No owin.Environment item was found in the context.
SimpleInjector Registration Code:
container.RegisterPerWebRequest<IUserStore<ApplicationUser>>(() => new UserStore<ApplicationUser>());
container.RegisterPerWebRequest<HttpContextBase>(() => new HttpContextWrapper(HttpContext.Current));
// app fails on call to line below...
container.RegisterPerWebRequest(() => container.GetInstance<HttpContextBase>().GetOwinContext());
container.RegisterPerWebRequest(() => container.GetInstance<IOwinContext>().Authentication);
container.RegisterPerWebRequest<DbContext, ApplicationDbContext>();
Update - Full Stack Trace
at
System.Web.HttpContextBaseExtensions.GetOwinContext(HttpContextBase
context) at
WebApplication1.App_Start.SimpleInjectorInitializer.<>c__DisplayClass6.b__2()
in
b:\temp\WebApplication1\WebApplication1\App_Start\SimpleInjectorInitializer.cs:line
41 at lambda_method(Closure ) at
SimpleInjector.Scope.CreateAndCacheInstance[TService,TImplementation](ScopedRegistration2
registration) at
SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration2
registration) at
SimpleInjector.Scope.GetInstance[TService,TImplementation](ScopedRegistration2
registration, Scope scope) at
SimpleInjector.Advanced.Internal.LazyScopedRegistration2.GetInstance(Scope
scope) at lambda_method(Closure ) at
SimpleInjector.InstanceProducer.GetInstance()

I think the exception is thrown when you call Verify(). Probably at that line, but only when the delegate is called.
Simple Injector allows making registrations in any order and will therefore not verify the existence and correctness of a registration’s dependencies. This verification is done the very first time an instance is requested, or can be triggered by calling .Verify() at the end of the registration process.
I suspect you're registrering the OwinContext only because you need it for getting the IAuthenticationManager.
The problem you face is that the OwinContext is only available when there is a HttpContext. This context is not available at the time the application is build in the composition root. What you need is a delegate which checks the stage of the application and returns a component that matches this stage. You could that by registering the IAuthenticationManager as:
container.RegisterPerWebRequest<IAuthenticationManager>(() =>
AdvancedExtensions.IsVerifying(container)
? new OwinContext(new Dictionary<string, object>()).Authentication
: HttpContext.Current.GetOwinContext().Authentication);
The delegate will return the Owin controlled IAuthenticationManager when the code runs at 'normal runtime stage' and there is a HttpContext.
But when making an explicit call the Verify() (which is highly advisable to do!) at the end of registration process there is no HttpContext. Therefore we will create a new OwinContext during verifying the container and return the Authentication component from this newly created OwinContext. But only if the container is indeed verifying!
A full and detailed description can be read here as already mentioned in the comments.

Although the question is different, the answer is the same as my answer here.
The problem is that you are injecting HttpContextWrapper into your application and attempting to use its members during application initialization, but at that point in the application lifecycle, HttpContext is not yet available. HttpContext contains runtime state, and it does not make sense to initialize an application within one specific user's context.
To get around this problem, you should use one or more Abstract Factories to access HttpContext at runtime (when it is available) rather than at application initialization, and inject the factories into your services with DI.
Using Ric .Net's answer might work, too, but it will throw an exception every time the application is initialized.

The answer of 'Ric .Net' has pointed me in right direction, but to allow changes to new SimpleInjector, have to change the code as below (as RegisterPerWebRequest is obselete):
container.Register<IAuthenticationManager>(() => AdvancedExtensions.IsVerifying(container)
? new OwinContext(new Dictionary<string, object>()).Authentication
: HttpContext.Current.GetOwinContext().Authentication, Lifestyle.Scoped);
Also, have to add below two registrations to the container, to allow 'container.Verify()' to work correctly:
container.Register<ApplicationUserManager>(Lifestyle.Scoped);
container.Register<ApplicationSignInManager>(Lifestyle.Scoped);

Related

Azure Function - Can you acccess IServiceProvider Before Function Scope?

Hi I have a use case that would be desireable to gain access to IServiceProvider before a function invoke in azure function project.
Attempts:
Using a IWebJobsStartup cs file, I am able to access the serviceCollection before a function invoke. at the end I have attempted this code
var serviceProvider = services.BuildServiceProvider();
serviceProvider.GetRequiredService<IAccountAPITests>();
with in error message "System.InvalidOperationException: 'Unable to resolve service for type 'Microsoft.Azure.WebJobs.Script.IFileLoggingStatusManager' while attempting to activate 'Microsoft.Azure.WebJobs.Script.Diagnostics.HostFileLoggerProvider'.'"
The only time I can access IServiceCollection so far is with in my funciton
public TestAutomationFunction
(
IServiceProvider rootServiceProvider
)
{
_integrationTestService = rootServiceProvider.GetRequiredService<IIntegrationTestService>();
}
This works fine, But the issues is functions are scoped, and thus anything that is resolved with in it will be tied to its same scope.
I did my best to draw a viso of why I dont have this problem in ASP.net and why i do in functions.
I would like to either access IServiceProvider Before a function invoke to ensure my services are not in the same scope. Or after the function is invoked resolve my services with in a spereate scope.
I can of course just change Package X singleton to a scoped, but my use case is not so simple as its deep in my stack i would have to do that all the way down.
This doenst quite answer my question but it makes my question a mute point.
"Do not resolve a scoped service from a singleton. It may cause the service to have incorrect state when processing subsequent requests. It's fine to resolve a singleton service from a scoped or transient service."
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection?view=aspnetcore-3.0#service-lifetimes
I am going to have re work my stack to not allow this to happen, after that I wont have to worry about this issue.

ServiceStack: AppHost does not support accessing the current Request via a Singleton

I'm encountering the following exception when trying using this.SessionAs<T> within one of my services:
"AppHost does not support accessing the current Request via a
Singleton"
The offending code is located within the constructor. Strangely, I'm only seeing this when the POST verb is used. I'm not yet sure if this is just a coincidence or not.
My apologies for not providing detailed information at this point. I'm trying to figure out which direction my troubleshooting should take. I'll edit as needed.
Thanks
Update - Stack trace
at ServiceStack.HostContext.GetCurrentRequest() at
ServiceStack.SessionFeature.GetOrCreateSession[T](ICacheClient cache,
IRequest httpReq, IResponse httpRes) at
ServiceStack.Service.SessionAsTUserSession at
PeruseServiceStack.Services.Settings.UserService..ctor() at
lambda_method(Closure , Container ) at
Funq.Container.ResolveImpl[TService](String name, Boolean
throwIfMissing)
I will be updating further shortly, I feel like this trace is incomplete.
From the StackTrace it looks like you're trying to access SessionAs<T> in your UserService constructor which you can't do because the Session can only be accessed within the context of a Request and the Service constructor does not have access to the injected IRequest context to be able to access the Session.
So you'd need to move SessionAs<T>() calls out of your constructor to within your Service implementation.

How to reload AWS options at runtime

I am running an ASP.NET Core MVC app in a docker container, with an AWS credentials file. I have another service that is putting new keys into the file when the old ones expire, but these new keys don't seem to propagate through to my MVC app and my site crashes. I have seen that normally the solution to get strongly typed configuration to reload is to use IOptionsSnapshot, like:
services.AddDefaultAWSOptions(Configuration.GetAWSOptions())
.AddScoped(config => config.GetService<IOptionsSnapshot<AWSOptions>>().Value)
.AddAWSService<IAmazonS3>();
but this gives an exception:
System.InvalidOperationException: Cannot resolve scoped service 'Amazon.Extensions.NETCore.Setup.AWSOptions' from root provider.
Does anyone have a solution to getting ASP to reload the AWS credentials file? I'd like to continue using the AWS dependency injection extension if possible.
By default, AddAWSService registers the client factory in singleton scope, which means it's one and done for the life of the application. However, AddAWSService has a lifetime param you can utilize to customize this. Essentially, you need a shorter lifetime on the client, so that it will be recreated with the new settings. You can choose either "scoped" (request-scoped) or "transient" (new instance every time it's injected).
Obviously with "scoped", you'll get a connection with the updated settings every request. However, if you do any further operations on the same request after the settings have been changed, it will remain the old connection with the old settings (i.e. you'll still have the same issue, at least for the life of the request).
Using "transient" scope, you'll have have a client with the most updated settings, but you'll end up basically with a client for every use, which may not be ideal.

Unity DI and custom Owin middleware

Custom Owin middleware eventually needs to verify credentials against the database, yet I can't find a way to get instances of repositories or the Asp.Net Identity UserManager from the middleware via DI.
Unfortunately my database driver is a global singleton and should be resolved by the configured Unity container. When debugging, the Unity child container for the request is created after the middleware gets called.
Is there any way to resolve dependencies with Unity in the middleware?
I tried this without success, but the namespace seems to be wrong anyway (System.Web.Mvc vs System.Web.Http)
var userManager = DependencyResolver.Current.GetService<ApplicationUserManager>();
It seems Autofac solves this by creating the request scope as a middleware itself. What about Unity?
UPDATE
This works
var userManager = (ApplicationUserManager)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(ApplicationUserManager));
However the child container (BeginScope of IDependencyResolver) is created later. I registered the UserManager with a HierarchicalLifetimeManager, which probably means it resolves a single instance in the parent container and subsequent requests get the same instance.
What's safer, using a TransientLifetimeManager and just resolve in the parent container, or are there better options?

Can i create OwinMiddleware per request instead creating a global object

I'm working on the webapi project & now we are migrating to Owin/Katana hosting. I have few doubts regarding.
Quest ) Can i create OwinMiddleware per request instead creating a global object?
I'm able to create owinMiddleware but not able to create them per request. I wanted to create them per request so that i can insert a new object in owinMiddleware as dependency. I'm already using unity in webapi so wanted some solution aligned with unity.
I found few links :-
http://alexmg.com/owin-support-for-the-web-api-2-and-mvc-5-integrations-in-autofac/
http://www.tugberkugurlu.com/archive/owin-dependencies--an-ioc-container-adapter-into-owin-pipeline
but not able to adjust a new IoC with old unity. Can anybody suggest any solution
I found a way by which we could achive this :-
app.Use((IOwinContext context, Func<Task> next) =>
{
ILogger logger = {Resolve dependency using Unity};
CustomOwinMiddleware middleware = new CustomOwinMiddleware(context,next, logger);
return middleware.Invoke();
});
By this way I'm able to generate my middle ware per request. Is it the right way to do this ?
I would recommend using a single middleware instance for all requests that can be injected with unity if you so choose. I would then create a lifetimemanager within the invoke method of that middleware and inject whatever functions you want as delegates rather than calling invoke on another middleware. If you need the OwinContext in those functions you can just pass them as parameters.
See this blog post here for more information:
http://codetoast.org/orchard/blog/using-unity-owin-and-web-api-to-organize-log-entries-by-request

Categories