Having problems to integrate into owin ASP.NET application
Closed this issue · 4 comments
Hello,
as far as I understand, there is nothing fancy about IDispatcher
that it could not work outside asp.net core
, it would just need an extra step as I show below.
I have an older base code which I cannot upgrade to .net core for now.
What I'm trying to do is manually create a ServiceCollection
and IConfigurationProvider
to build the dispatcher. It works, but I am having an issue integrating with Unity
.
On my Startup.cs
I have:
public IDispatcher ConfigureKledex()
{
var configurationProviders = new List<IConfigurationProvider>
{
new MemoryConfigurationProvider(new MemoryConfigurationSource()
{
InitialData = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("DomainDbConfiguration:ConnectionString",
WebConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString)
}
})
};
IConfiguration configuration = new ConfigurationRoot(configurationProviders);
var services = new ServiceCollection();
services.AddOptions();
services.AddKledex(typeof(DeactivateCompany))
.AddOptions(options =>
{
options.PublishEvents = false;
options.SaveCommandData = false;
})
.AddSqlServerProvider(configuration)
.AddServiceBusProvider(configuration)
;
var serviceProvider = services.BuildServiceProvider();
var dispatcher = serviceProvider.GetService<IDispatcher>();
return dispatcher;
}
then on my Startup.cs
I call it like this and it works!
//just for testing! IT WORKS <--
var command = DeactivateCompany.Create(1);
ConfigureKledex().SendAsync(command);
Naturally, I just needed now to register IDispatcher
on my Unity container
to inject into my controllers.
The gotcha is: For past constraints, I had to initialize my IUnityContainer
using WebActivatorEx
.
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(UnityWebActivator), "Start")]
namespace AMZ.MVC {
public class MvcApplication : HttpApplication {
...
}
}
public static class UnityWebActivator
{
/// <summary>Integrates Unity when the application starts.</summary>
public static void Start()
{
IUnityContainer container = UnityConfig.GetConfiguredWebContainer();
// MVC resolver.
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// Web API resolver
GlobalConfiguration.Configuration.DependencyResolver = new Unity.AspNet.WebApi.UnityDependencyResolver(container);
}
}
When now I try using my previously mentioned ConfigureKledex
method, say, as a factory,
IUnityContainer container = UnityConfig.GetConfiguredWebContainer();
container.RegisterFactory<IDispatcher>(container => ConfigureKledex());
it executes alike, but for some reason once moving into the static method of UnityMvcActivator
, this similar code line which would work just fine now stops working throwing an exception saying it could not find the command handler.
//this worked on Startup.cs but now it throws an exception
//saying the handler could not be found
var command = DeactivateCompany.Create(1);
ConfigureKledex().SendAsync(command);
The thing is: The same code which worked on Startup
(after container registration), simply after moving to the static
method of WebActivator
it started throwing the exception.
Would you have an idea of what is going on, on an alternative way to solve this issue?
What I understand is that I have to register IDispatcher
into Unity
and everything would work just as normal, despite being on an ASP.NET project. I would inject it into my controllers and it would just redirect the command to the appropriate handler.
Could it have something to do when webactivator
executes and Scrutor
? Maybe WebActivator
runs somehow in a way that is have not loaded assemblies or what yet?
Hello, updating the issue with my progress, so hopefully it can help someone in the future.
I have a question at the end.
Apparently I can get rid of WebActivator. I moved the initialization of my Unity
container to Global.asax.cs
file. It somehow fixes the problem I was having. I don't know why though.
Also, I'm using Unity.Microsoft.DependecyInjection
package so I can use my Unity
container together with ServiceCollection
class. Thus, I can inject anything I'm already using on my MVC application inside my commands just like normal; say, my dbcontext.
Here is my new factory method so far:
static IDispatcher ConfigureKledex(IUnityContainer container)
{
var configurationProviders = new List<IConfigurationProvider>
{
new MemoryConfigurationProvider(new MemoryConfigurationSource()
{
InitialData = new List<KeyValuePair<string, string>>()
{
new KeyValuePair<string, string>("DomainDbConfiguration:ConnectionString",
WebConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString)
}
})
};
IConfiguration configuration = new ConfigurationRoot(configurationProviders);
ServiceCollection services = new ServiceCollection();
services.AddOptions();
services.AddKledex(typeof(DeactivateCompany))
.AddOptions(options =>
{
options.PublishEvents = false;
options.SaveCommandData = false;
})
.AddSqlServerProvider(configuration)
.AddServiceBusProvider(configuration)
;
var serviceProvider = services.BuildServiceProvider(container);
var dispatcher = serviceProvider.GetService<IDispatcher>();
return dispatcher;
}
And the code which was on the WebActivator class now is the first thing on Global.asax.cs
Application_Start
method.
protected void Application_Start()
{
var container = UnityConfig.GetConfiguredWebContainer();
container.RegisterFactory<IDispatcher>(ConfigureKledex);
// MVC resolver.
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// Web API resolver
GlobalConfiguration.Configuration.DependencyResolver = new Unity.AspNet.WebApi.UnityDependencyResolver(container);
//...
}
By using the RegisterFactory
method without an explicit lifetime manager, it uses Transient
by default. I guess it will work; otherwise, I post an update here.
I guess what I'm doing is correct so far. I run your wiki configuration code to configure the ServiceCollection
Kledex uses internally, and I'm resolving the IDispatcher
from it and using as the result of the Unity
factory.
Would you have any observations to make on how I'm handling it? Any misconception I've not spotted?
I'm not a Unity expert but I'm assuming that what you are doing is correct and thanks for sharing your solution, it could help someone else :-)
Closing as I'm assuming it is resolved.