-
Notifications
You must be signed in to change notification settings - Fork 456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
UseMiddlewareFromWindsor cannot pass arguments into the middleware #411
Comments
… rolls back DB transaction. Allowing to pass isolation level into the middleware (created a new issue for Windsor Castle - castleproject/Windsor#411).
Here is the revised pseudo method: public static void UseMiddlewareFromWindsor<T>(this IApplicationBuilder app, IWindsorContainer container, object argumentsAsAnonymousType == null /*Already used in prod sorry, no breaking changes*/)
where T : class, IMiddleware
{
container.Register(Component.For<T>());
app.Use(async (context, next) =>
{
T resolve = default(T);
if (argumentsAsAnonymousType == null) { // <- We need to make sure we pick the right overload for the interface IWindsorContainer
resolve = container.Resolve<T>();
} else {
resolve = container.Resolve<T>(argumentsAsAnonymousType);
}
try
{
await resolve.InvokeAsync(context, async (ctx) => await next());
}
finally
{
container.Release(resolve);
}
});
} If you are happy with this, I will do it with tests, docs and performance tests. |
/cc @generik0 |
Like it a lot 👍 ta |
I am a bit worried about this interface @xhafan, it overrides lifestyles from a singleton point of view. The problem is If your answer is to use typed factories it is important to note there is a slight memory leak which has not been completely verified/fixed yet. #410 For Example:
Think we need to look at these things in detail before we expose another public API for resolution on middleware from the IWindsorContainer. Thoughts? |
@fir3pho3nixx, the original Btw I can see another issue - the middleware is registered a singleton, and passing an argument into Resolve method makes an impression that the middleware is not a singleton.
The example of the usage is the same:
I just need to pass data - not resolvable dependencies - into the middleware. I thought that by using |
I'm a complete moron - I actually don't need to use |
After you raised this issue, and it got me round to thinking this could be improved. Sorry if you took this as me rejecting your idea. If you check the PR I flagged this public API as rubbish in the PR here anyway. I do think we should try and remove the container as a parameter. It also does not feel like we have an implementation which expresses lifestyle concerns properly.
Correct! We need to figure this out a little bit more, this is what I originally meant. We already addressed this issue with cross wiring using a CMC via facility. Will investigate how we achieve this for middleware in the meantime.
Yep, I am just thinking of the consequences of clashing lifestyles for exposing IWindsorContainer.Resolve(object) via middleware. Glad you raised this issue :)
Don't think you did anything of the sort :) |
Can we re-open this please? |
Re-opened, I'm glad it at least triggered something useful. |
Great. :) Please tell me about your usage? Interested to know some details. You did mention IsolationLevel.ReadCommitted in the description and alluded to a Unit of work pattern here. If I had to guess, you are trying to implement ACID(using read committed transactions down to your Sql Db) for each request using middleware right? |
I think the final results are in for this PR The problems we are trying to address here from what I can see are:
Consider the enhanced code for middleware: public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// For making component registrations of middleware easier
Container.GetFacility<AspNetCoreFacility>().RegistersMiddlewareInto(app);
// Add custom middleware, do this if your middleware uses DI from Windsor
Container.Register(Component.For<CustomMiddleware>().DependsOn(Dependency.OnValue<ILoggerFactory>(loggerFactory)).LifestyleScoped().AsMiddleware());
// ...
} Once I found a way of glueing the
This does mean one massive breaking change which I was rather hoping to avoid but I still think this has left us in a much better place. I don't think I will be supporting the If you are happy with these changes I will merge and close out this issue. Thanks for participating as an early adopter! :) |
Yes, I have a transaction scope unit of work middleware, which wraps ASP.NET Core request into a transaction scope. As I mentioned previously, I don't have any dependencies, so I can just use standard
I tried to use this new way of registering a middleware using
I'm a little bit lost here. My impression was that a middleware instance is a singleton, so I'm not sure allowing a middleware to be transient or scoped would be useful. I wanted to try it with my |
Hi. https://github.com/generik0/Smooth.IoC.Dapper.Repository.UnitOfWork |
@fir3pho3nixx, I wanted to try previous commits to discover what is the last commit which works for me for aspnet-core-windsor-final branch. But I'm not able to find the history of commits I can try. For instance, looking at the branch commits, the commit from Apr 26 does not contain the extension method |
@generik0, are you saying there is a benefit resolving unit of work via a factory instead of resolving it from a container? |
@xhafan I am saying that a factory is resolvable from the container. So you ctor injects a dbfactory Or look at https://github.com/generik0/Smooth.IoC.Dapper.Repository.UnitOfWork |
I found out why it gives me an error It looks like the ASP.NET Core build in DI container is not able to resolve a controller's dependencies. |
@generik0, ok I think I get it. So the point is to inject the unit of work factory into my middleware, and use it to create unit of work instances, instead of using the container instance directly. Right? |
@xhafan check :-) |
@generik0 thanks for the advice |
This is simply an extension of middleware that wraps resolve/release inside other middleware. One
Yes, scopes were fun. I found massive discrepancies between middleware being registered and called somehow the scope was not there. I tried to combat this by ensuring the scope was provisioned in the middleware first here. Looks like we have a bug, nothing should be resolving without a scope first. I will check this again and get back to you.
Confirmed will fix. Was simply hoping for middleware that would simply new up an outer TransactionScope in the ctor and then get rid of it by implementing IDisposable using a scoped lifestyle. Man, did
This is probably why I have not merged the PR yet. We use a 2 container solution in this facility. What we attempted here was to let ASP.NET do it's thing(which mean's let it have it's own native container, ServiceProvider) and then we adapt the IWindsorContainer to it by using the ASP.NET Core activators for controllers, taghelpers and viewcomponents and by allowing
Please implement container.Register(
Classes
.FromAssemblyContaining<GetEmailQueryHandler>()
.BasedOn(typeof(IQueryHandler<>))
.WithService.FirstInterface()
.Configure(x => x.LifestyleTransient().CrossWired())); |
@xhafan Just to be clear. I really think you should hold off on upgrading until I have fixed this. We should at least remove the CrossWiring dependency from your IQueryHandler registration. Give me some time to look into this. |
@xhafan Can you please take a look at the latest cut? You also should not need to cross wire anything. I am going to drop this into production tomorrow. If I find anything I will let you know. |
@fir3pho3nixx, the latest cut works for me, thanks. |
Awesome. We did not notice any memory spikes either. Closing for now. Please raise new issues when you find them. |
This issue is related to https://github.com/fir3pho3nixx/Windsor/tree/aspnet-core-windsor-final branch
UseMiddlewareFromWindsor extension method (https://github.com/fir3pho3nixx/Windsor/blob/fa3617bf19e4f53430e018d543ababa00388e005/src/Castle.Facilities.AspNetCore/WindsorRegistrationExtensions.cs#L90) cannot pass arguments into the middleware.
I had to come up with a modified version with a new parameter argumentsAsAnonymousType:
Example of usage:
app.UseMiddlewareFromWindsor<TransactionScopeUnitOfWorkMiddleware>(_windsorContainer, new { isolationLevel = IsolationLevel.ReadCommitted });
In this example it passes read committed isolation level into the TransactionScopeUnitOfWorkMiddleware.
Should I create a pull request? Or do you think this can be added by you? Cheers.
The text was updated successfully, but these errors were encountered: