Simple Injector - difficulty with ASP.NET 5 Identity and RavenDB - c#

I am attempting to use SimpleInjector with ASP.NET 5 on an MVC application, and am running into a major problem getting it wired up right.
I run a RavenDB database, and as such I have methods for instantiating instances to it, which is what I use when registering the interfaces, like this;
private void InitializeContainer(IApplicationBuilder app) {
container.CrossWire<IUserStore<AppUser>>(app);
container.CrossWire<UserManager<AppUser>>(app);
container.CrossWire<SignInManager<AppUser>>(app);
container.CrossWire<ILoggerFactory>(app);
container.Register<IDocumentStore>(RavenDatabase.OpenDatabase);
container.Register<IDocumentSession>(RavenDatabase.OpenSession);
container.Register<IAsyncDocumentSession>(RavenDatabase.OpenAsyncSession);
container.Register<ILookupNormalizer>(() => new LowerInvariantLookupNormalizer());
container.Register<IPasswordHasher<AppUser>>(() => new PasswordHasher<AppUser>());
}
The problem seems to be with IUserStore. When I try to load up the application, I get this exception..
Unable to resolve service for type 'Raven.Client.IAsyncDocumentSession' while attempting to activate 'App.Identity.UserStore`1[App.Identity.AppUser]'.
I'm really uncertain why this is, though. I've registered IAsyncDocumentSession, so why can't it inject it? I've also tried it like this...
container.Register<IUserStore<AppUser>>(RavenDatabase.UserStore);
With a method defined as such...
public static UserStore<AppUser> UserStore() {
// check to see if we even have a session factory to get a session from
if (documentStore == null)
OpenDatabase();
return new UserStore<AppUser>(documentStore.OpenAsyncSession());
}
But I still continue to get the exception. I'm at a loss, here. This is my first time using Simple Injector.
Stack Trace
System.InvalidOperationException
Unable to resolve service for type 'Raven.Client.IAsyncDocumentSession' while attempting to activate 'App.Identity.UserStore`1[App.Identity.AppUser]'.
at Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.PopulateCallSites(ServiceProvider provider, ISet<Type> callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.CreateCallSite(ServiceProvider provider, ISet<Type> callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetResolveCallSite(IService service, ISet<Type> callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetServiceCallSite(Type serviceType, ISet<Type> callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.PopulateCallSites(ServiceProvider provider, ISet<Type> callSiteChain, ParameterInfo[] parameters, Boolean throwIfCallSiteNotFound)
at Microsoft.Extensions.DependencyInjection.ServiceLookup.Service.CreateCallSite(ServiceProvider provider, ISet<Type> callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetResolveCallSite(IService service, ISet<Type> callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetServiceCallSite(Type serviceType, ISet<Type> callSiteChain)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.CreateServiceAccessor(Type serviceType, ServiceProvider serviceProvider)
at System.Collections.Concurrent.ConcurrentDictionaryExtensions.GetOrAdd<TKey, TValue, TArg>(ConcurrentDictionary<TKey, TValue> dictionary, TKey key, Func<TKey, TArg, TValue> valueFactory, TArg arg)
at Microsoft.Extensions.DependencyInjection.ServiceProvider.GetService(Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
at Microsoft.Extensions.DependencyInjection.ServiceProviderExtensions.GetRequiredService<T>(IServiceProvider provider)
.lambda_method(Closure )
at SimpleInjector.InstanceProducer.BuildAndReplaceInstanceCreatorAndCreateFirstInstance()
at SimpleInjector.InstanceProducer.GetInstance()
SimpleInjector.ActivationException
Unable to resolve service for type 'Raven.Client.IAsyncDocumentSession' while attempting to activate 'App.Identity.UserStore`1[App.Identity.AppUser]'.
at SimpleInjector.InstanceProducer.GetInstance()
at SimpleInjector.InstanceProducer.VerifyInstanceCreation()
System.InvalidOperationException
The configuration is invalid. Creating the instance for type LoginController failed. Unable to resolve service for type 'Raven.Client.IAsyncDocumentSession' while attempting to activate 'App.Identity.UserStore`1[App.Identity.AppUser]'.
System.Reflection.TargetInvocationException
Exception has been thrown by the target of an invocation.
at System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at Microsoft.AspNet.Hosting.Startup.ConfigureBuilder.Invoke(Object instance, IApplicationBuilder builder)
at Microsoft.AspNet.Hosting.Startup.ConfigureBuilder.<>c__DisplayClass4_0.<Build>b__0(IApplicationBuilder builder)
at Microsoft.AspNet.Hosting.Internal.AutoRequestServicesStartupFilter.<>c__DisplayClass0_0.<Configure>b__0(IApplicationBuilder builder)
at Microsoft.AspNet.Hosting.Internal.HostingEngine.BuildApplication()

As far as I can see, this problem is not related to Simple Injector. From your registrations, and the exception information I see the following is the case:
You are resolving a LoginController from Simple Injector.
This LoginController depends on Raven.Client.IAsyncDocumentSession.
IAsyncDocumentSession is cross-wired from the ASP.NET configuration system to Simple Injector using CrossWire<IAsyncDocumentSession>.
IAsyncDocumentSession is registered in the ASP.NET configuration system.
The implementation of IAsyncDocumentSession that is registered in ASP.NET depends on UserStore<AppUser>.
The ASP.NET configuration system is unable to resolve that IAsyncDocumentSession registration and throws the exception stating:
Unable to resolve service for type 'Raven.Client.IAsyncDocumentSession' while attempting to activate 'App.Identity.UserStore`1[App.Identity.AppUser]'.
In other words, you would get the same exception when you would either resolve LoginController or IAsyncDocumentSession from the ASP.NET configuration system. Just call one of the following methods and you will see the same error:
app.ApplicationServices.GetRequiredService<LoginController>();
// or
app.ApplicationServices.GetRequiredService<IAsyncDocumentSession>();
I think that the IAsyncDocumentSession implementation depends on UserStore<T> or IUserStore<T>, but you haven't registered it in the ASP.NET configuration system.

Related

Nswag client generator tries to generate when azure secrets are added

In the project I am involved with now, we are using dotnet-nswag.dll to generate a typescript api client. I am now trying to switch from using local secrets to secrets stored in azure key vault (I hope to simplify new developers' entry to the project). I however bumped into a problem, that when I use something like below:
builder.ConfigureAppConfiguration((ctx, cfg) =>
{
if (ctx.HostingEnvironment.IsDevelopment())
{
var keyVaultEndpoint = new Uri(Environment.GetEnvironmentVariable("DevEnv_KVUri"));
cfg.AddAzureKeyVault(keyVaultEndpoint, new DefaultAzureCredential());
}
});
I no longer can generate the nswag typescript api client. My investigation led me to the discovery that nswag fails becasue DevEnd_KVUri does not exists at the generation time. I have this env var added in my launchSettigns.json and it is available when I test my app. However, I would like to instruct nswag not to try to include whatever is triggering it to also go through that key vault endpoint.
If I hard-code the url (and it is a KeyVault url that I have access to), then the generation passes. Generated client does not have any endpoints pointing to my hard-coded url. However I do not like the solution, where I have to hard-code (not even fake but a working one) my key vault address.
Unfortunately, I did not find any solution to my problem.
Edit 1:
The command that executes generation:
dotnet "C:\Users\myname\.nuget\packages\nswag.msbuild\13.16.0\build\../tools/Net50/dotnet-nswag.dll" run nswag.json /variables:Configuration=Debug`
The exception thrown by the generator when no url is provided
System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation.
---> System.ArgumentNullException: Value cannot be null. (Parameter 'uriString')
at System.Uri..ctor(String uriString)
at Lib.KeyVault.Extensions.IWebHostBuilderExtensions.<>c.<UseKeyVault>b__0_1(HostBuilderContext ctx, IConfigurationBuilder bld) in C:\dotnet\net\lib\Lib.KeyVault.Extensions\IWebHostBuilderExtensions.cs:line 50
at Microsoft.Extensions.Hosting.HostBuilder.BuildAppConfiguration()
at Microsoft.Extensions.Hosting.HostBuilder.Build()
at NSwag.Commands.ServiceProviderResolver.GetServiceProvider(Assembly assembly) in /_/src/NSwag.Commands/HostApplication.cs:line 61
at NSwag.Commands.Generation.AspNetCore.AspNetCoreToOpenApiGeneratorCommandEntryPoint.Process(String commandContent, String outputFile, String applicationName) in /_/src/NSwag.Commands/Commands/Generation/AspNetCore/AspNetCoreToOpenApiGeneratorCommandEntryPoint.cs:line 27
--- End of inner exception stack trace ---
at System.RuntimeMethodHandle.InvokeMethod(Object target, Span`1& arguments, Signature sig, Boolean constructor, Boolean wrapExceptions)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj, BindingFlags invokeAttr, Binder binder, Object[] parameters, CultureInfo culture)
at System.Reflection.MethodBase.Invoke(Object obj, Object[] parameters)
at NSwag.AspNetCore.Launcher.Program.Main(String[] args) in /_/src/NSwag.AspNetCore.Launcher/Program.cs:line 132
System.InvalidOperationException: Swagger generation failed with non-zero exit code '1'.
at NSwag.Commands.Generation.AspNetCore.AspNetCoreToSwaggerCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in /_/src/NSwag.Commands/Commands/Generation/AspNetCore/AspNetCoreToOpenApiCommand.cs:line 231
at NSwag.Commands.NSwagDocumentBase.GenerateSwaggerDocumentAsync() in /_/src/NSwag.Commands/NSwagDocumentBase.cs:line 275
at NSwag.Commands.NSwagDocument.ExecuteAsync() in /_/src/NSwag.Commands/NSwagDocument.cs:line 81
at NSwag.Commands.Document.ExecuteDocumentCommand.ExecuteDocumentAsync(IConsoleHost host, String filePath) in /_/src/NSwag.Commands/Commands/Document/ExecuteDocumentCommand.cs:line 85
at NSwag.Commands.Document.ExecuteDocumentCommand.RunAsync(CommandLineProcessor processor, IConsoleHost host) in /_/src/NSwag.Commands/Commands/Document/ExecuteDocumentCommand.cs:line 32
at NConsole.CommandLineProcessor.ProcessSingleAsync(String[] args, Object input)
at NConsole.CommandLineProcessor.ProcessAsync(String[] args, Object input)
at NSwag.Commands.NSwagCommandProcessor.ProcessAsync(String[] args) in /_/src/NSwag.Commands/NSwagCommandProcessor.cs:line 61

DryIoc : Can't figure out how to register IDisposable Decorator object

I'm trying to setup a decorator around an IDisposable db context:
c.Register<IContext, DbContext>(setup: Setup.With(trackDisposableTransient: true));
// c.Register<IContext, ConsoleTimedContext>(setup: Setup.Decorator);
If i uncomment the last line, the program throws:
DryIoc.ContainerException: Registered Disposable Transient service Lib.DI.IContext with key {no key} and factory container won't be disposed by container. DryIoc does not hold reference to resolved transients, and therefore does not control their dispose. To silence this exception Register<YourService>(setup: Setup.With(allowDisposableTransient: true)) or set the rule Container(rules => rules.WithoutThrowOnRegisteringDisposableTransient()). To enable tracking use Register<YourService>(setup: Setup.With(trackDisposableTransient: true)) or set the rule Container(rules => rules.WithTrackingDisposableTransient())
à DryIoc.Throw.It(Int32 error, Object arg0, Object arg1, Object arg2, Object arg3)
à DryIoc.Container.ThrowIfInvalidRegistration(Factory factory, Type serviceType, Object serviceKey, Boolean isStaticallyChecked)
à DryIoc.Container.Register(Factory factory, Type serviceType, Object serviceKey, IfAlreadyRegistered ifAlreadyRegistered, Boolean isStaticallyChecked)
à DryIoc.Registrator.Register[TService,TImplementation](IRegistrator registrator, IReuse reuse, Made made, Setup setup, IfAlreadyRegistered ifAlreadyRegistered, Object serviceKey)
How to mix Setup.Decorator with trackDisposableTransient?
The setting is not available per Decorator registration (as of latest DryIoc v2.8.3).
For now you need to specify non transient reuse for decorator.
Feel free to raise an issue at: https://bitbucket.org/dadhi/dryioc

LightInject Attempt to create a scoped instance without a current scope

I (noob to light inject mvc) am using LightInject MVC in my asp.mvc 4 app with great results except an occasional exception. Now I am seeing it in pre-production. The exception is: System.InvalidOperationException: Attempt to create a scoped instance without a current scope.
My app start code is:
var container = new LightInject.ServiceContainer();
container.RegisterControllers();
container.RegisterAssembly(typeof(AppDDD.RegisterMe).Assembly, () => new PerScopeLifetime());
... scoped registrations
container.EnableMvc();
I get the error with a stack trace like:
System.InvalidOperationException: An error occurred when trying to
create a controller of type 'MvcAPP.Controllers.HomeController'. Make
sure that the controller has a parameterless public constructor. --->
System.InvalidOperationException: Attempt to create a scoped instance
without a current scope. at
LightInject.PerScopeLifetime.GetInstance(Func1 createInstance, Scope
scope) at DynamicMethod(Object[] ) at
LightInject.ServiceContainer.<>c__DisplayClass40.<WrapAsFuncDelegate>b__3f()
at LightInject.PerRequestLifeTime.GetInstance(Func1 createInstance,
Scope scope) at DynamicMethod(Object[] ) at
LightInject.ServiceContainer.TryGetInstance(Type serviceType) at
System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create(RequestContext
requestContext, Type controllerType) --- End of inner exception
stack trace --- at
System.Web.Mvc.DefaultControllerFactory.DefaultControllerActivator.Create(RequestContext
requestContext, Type controllerType) at
System.Web.Mvc.DefaultControllerFactory.CreateController(RequestContext
requestContext, String controllerName) at
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase
httpContext, IController& controller, IControllerFactory& factory)
at System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase
httpContext, AsyncCallback callback, Object state) at
System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step,
Boolean& completedSynchronously)
I have created a couple of small test ASP MVC projects to isolate the exception with no success.
The Controllers are scoped per instance, and all the objects with in each instance are designated PerScopeLifetime.
Is there a tweak I can make, or should I stop using PerScopeLifetime? I must have scoped lifetimes for my EF contexts.
The exception is thrown before my controllers finish constructing, so it appears.
I would like you to know that the issue has been resolved and getting the latest and greatest from NuGet should fix your problem.
Best regards
Bernhard Richter

access to the Object property after new Mock<RadNumericTextBox>() leads to NullReferenceException

I have to write some tests using moq framework (https://code.google.com/p/moq/). I want to check if some value can be read correctly from a telerik textbox in some ASP.NET application. Therefore I want to mock the telerik text box and give this mock as a parameter to the SUT's method to check if it is read correctly.
Consider:
var telerikFake = new Mock<RadNumericTextBox>();
telerikFake.Setup(x => x.Text).Returns("23,456");
var result = telerikFake.Object; //The exception comes from inside the telerikFake.Object property implementation
Accessing the telerikFake.Object property gives a NullReferenceException with this stack trace:
at Castle.DynamicProxy.AttributeUtil.<GetNonInheritableAttributes>d__0.MoveNext()
at Castle.DynamicProxy.Contributors.ClassProxyInstanceContributor.Generate(ClassEmitter class, ProxyGenerationOptions options)
at Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateType(String name, Type[] interfaces, INamingScope namingScope)
at Castle.DynamicProxy.Generators.ClassProxyGenerator.GenerateCode(Type[] interfaces, ProxyGenerationOptions options)
at Castle.DynamicProxy.DefaultProxyBuilder.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxyType(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options)
at Castle.DynamicProxy.ProxyGenerator.CreateClassProxy(Type classToProxy, Type[] additionalInterfacesToProxy, ProxyGenerationOptions options, Object[] constructorArguments, IInterceptor[] interceptors)
at Moq.Proxy.CastleProxyFactory.CreateProxy[T](ICallInterceptor interceptor, Type[] interfaces, Object[] arguments)
at Moq.Mock`1.<InitializeInstance>b__0()
at Moq.PexProtector.Invoke(Action action)
Do you have any hints under what circumstances the moq frameworks Mock.Object method leads to this error?
I found a ticket within the MoQ issue list: http://code.google.com/p/moq/issues/detail?id=326 . Are there any developers enabled to fix this issue soon? The ticket was created in 2011.
Regards,
Michael

Ninject: How to not use the Ninject in "ashx" file and still not get an exception?

This is what i use to implement an Dependency Injection in my MVC3 project,
public class NinjectControllerFactory : DefaultControllerFactory
{
private readonly IKernel _ninjectKernel;
public NinjectControllerFactory()
{
_ninjectKernel = new StandardKernel();
AddBindings();
}
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
return controllerType == null ? null : (IController)_ninjectKernel.Get(controllerType);
}
private void AddBindings()
{
_ninjectKernel.Bind<IUserRepository>().To<UserRepository>().InSingletonScope();
}
}
but i have a huge problem i want to use an Generic Handler an ".ashx" to implement my logic.
But i get an exception because the httphandler is not a Controller.
here is the exception:
Server Error in '/' Application.
The IControllerFactory 'Infrastructure.NinjectFactory.NinjectControllerFactory' did not return a controller for the name 'registercustomer.ashx'.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: The IControllerFactory 'Infrastructure.NinjectFactory.NinjectControllerFactory' did not return a controller for the name 'registercustomer.ashx'.
Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.
Stack Trace:
[InvalidOperationException: The IControllerFactory 'Infrastructure.NinjectFactory.NinjectControllerFactory' did not return a controller for the name 'registercustomer.ashx'.]
System.Web.Mvc.MvcHandler.ProcessRequestInit(HttpContextBase httpContext, IController& controller, IControllerFactory& factory) +422803
System.Web.Mvc.<>c__DisplayClass6.<BeginProcessRequest>b__2() +49
System.Web.Mvc.<>c__DisplayClassb`1.<ProcessInApplicationTrust>b__a() +13
System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Func`1 func) +124
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContextBase httpContext, AsyncCallback callback, Object state) +98
System.Web.Mvc.MvcHandler.BeginProcessRequest(HttpContext httpContext, AsyncCallback callback, Object state) +50
System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.BeginProcessRequest(HttpContext context, AsyncCallback cb, Object extraData) +16
System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +8971636
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +184
Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.547
Now is the question: How do i implement the work around this bug, to me to be able to an HttpHandler and still remain using the Ninject in my project?
Thanks in advance.
Due to the HttpHandler being created by the framework and there is no hook or factory method to intercept the creation of the ashx file, ninject is not able to create this object.
However you can use service locator calls or property injection from the ashx to request dependancies from the ashx code. But as far as I know, the ashx must have a default constructor, and you can then either resolve the dependancies from inside the constructor (or anywhere really) via service locator (less preferred method) or via property injection simply like this:
public class Handler
{
[Inject]
public IService Service { get; set; }
}
EDIT: also, to tell mvc to not process the ashx file you need to add this to ignore the route:
routes.IgnoreRoute("{resource}.ashx/{*pathInfo}");

Categories