ASP.NET Controller activation fails
jods4 opened this issue · comments
I encountered a blocking bug that I can't explain.
I use Grace as IoC container in my asp.net core project, set up as described in Grace.AspNetCore.(Hosting,Mvc)
.
My ASP.NET Core controllers are created by DI, thanks to:
services.AddMvcCore().AddControllersAsServices()
(Notice that I don't add controllers to Grace directly, it's only done by the ASP.NET call above).
I have split my application in multiple assembly and I now notice that controllers that inject classes from other assemblies fail, although the classes are registered in the Grace container (locating them works).
Here are some error details.
Consider a basic Test
class:
[Export] class Test { }
(Registration is made by attributes, I observed that this happens after ASP.NET Core registrations such as controllers above)
Consider a basic HelloController
that imports Test
:
[Route("hello")]
public class HelloController
{
public HelloController(Test t)
{ }
}
When Test
is in the main assembly, this works fine.
But when Test
is in another assembly (which is also imported into Grace at startup, more on that later) then locating the controller fails:
Grace.DependencyInjection.Exceptions.LocateException: Could not locate Type Portal.Test
1 Importing Portal.Controllers.HelloController
2 Importing Portal.Test for constructor parameter t
at Grace.DependencyInjection.Impl.InjectionContextValueProvider.GetValueFromInjectionContext[T](IExportLocatorScope locator, StaticInjectionContext staticContext, Object key, IInjectionContext dataProvider, Object defaultValue, Boolean useDefault, Boolean isRequired)
at lambda_method195(Closure , IExportLocatorScope , IDisposalScope , IInjectionContext )
at Grace.AspNetCore.MVC.GraceControllerActivator.Create(ControllerContext context)
at Microsoft.AspNetCore.Mvc.Controllers.ControllerFactoryProvider.<>c__DisplayClass5_0.<CreateControllerFactory>g__CreateController|0(ControllerContext controllerContext)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
I do not understand this problem because if I inspect the container at the end of ConfigureContainer
, then clearly Test
is there.
From WhatDoIHave
:
--------------------------------------------------------------------------------
Export Type: Portal.Controllers.HelloController
As Type: Portal.Controllers.HelloController
Priority: 0
Externally Owned: False
Lifestyle: Transient
Depends On
Dependency Type: ConstructorParameter
Member Name: t
Import Type: Portal.Test
Has Filter: False
Has Value Provider: False
Is Satisfied: False
--------------------------------------------------------------------------------
Export Type: Portal.Test
As Type: Portal.Test
Priority: 0
Externally Owned: False
Lifestyle: Transient
Depends On
None
Notice that HelloController
says Is Satisfied: False
, although Test
is clearly in there.
Doing scope.Locate<Test>()
works, but scope.Locate<HelloController>()
fails.
Any idea what can be causing this?
Is there anything I could do to try and debug this issue? Thanks!
Not sure if that's expected or not, but I just noticed (HelloController).TypeBeingImported != (Test).ActivationType
.
That's surprising to me, trying to figure out why (.net 5.0).
EDIT: no, that's extremely suspicious, probably why it fails.
According to MSDN, Types can be compared for equality:
https://docs.microsoft.com/en-us/dotnet/api/system.type?view=net-5.0#comparing-type-objects-for-equality
I wonder if I found a bug in .net 5.0...
Sorry for the noise, digging further I found the error and it's in my code.
I used Assembly.LoadFile
to dynamically load all assemblies, and it turns out this way can load the same assembly twice (with different types, then). Assembly.LoadFrom
is the way to go and fixes the problem.