How to receive IHubContext out of Dependency Injected classes? - asp.net-core

I want to send message from Service A using SignalR when some event occures (for example, message from Service B received).
So hub method needs to be called from some sort of handler, that not constructed using Dependency Injection. How I can do this?
So far, I tried and read about the following things:
I can inject context into Controller and lead it to my handler. I probably can do that, but passing hub context from the top (controller class) to the bottom (handler class) is not the best approach, which adds a lot of dependencies to the classes that should not be aware of this context, so I would like to avoid that.
I can inject my IHubContext in "any" class, but then, the thing is, how to get an instance of that class on my handler?
Add Static method to class with injected context!? Well, that works until you have 1 client because with new client static property is going to be overwritten.
So I cannot imagine, how handler can use dependency injected IHubContext.
Probably, someone did that before and have an example of how to truly inject context into any class.
Thank you in advance and any additional information will be provided, if necessary.

Answer 1
Here is one possible solution. Implement a factory pattern. Create a factory that knows how to create your handler. Inject the IHubContext in the factory. You can use a few approaches that way:
Construct the Handler by passing in the IHubContext
Create a public property in the Handler and set the IHubContext
Create a method in the Handler and pass the IHubContext as a parameter
You can decide whichever approach suits you. Inject that factory in the controller via DI, and get the handler using the factory method. That way you are not exposing the IHubContext. Please see the code below
public interface IHandlerFactory
{
Handler CreateHandler();
}
public class HandlerFactory : IHandlerFactory
{
private IHubContext _hubContext;
public HandlerFactory(IHubContext context)
{
_hubContext = context;
}
public Handler CreateHandler()
{
return new Handler(param1, param2, _context);
}
}
Then in the entry point, controller/service, inject the factory via DI
public class MyController : Controller
{
private Handler _handler;
public MyController(IHandlerFactory factory)
{
_handler = factory.CreateHandler();
}
}
Then you can use that _handler in the other methods. I hope this helps.
Answer 2
Another possible solution is to use IHostedService if it's possible at all for you. Please see a solution to a GitHub issue, provided by David Fowler here, that I think somewhat relevant to your scenario.

Related

Implement class with private constructor in Kotlin

I'd like to write a little stub for a service class. The reason is, that I don't want to push the secret API keys that the service class needs to the CI and I don't want the service class in the CI to run against the external service anyways.
However, the service class is non-abstract and has a private constructor.
When I try to create my stub class like:
open class FirebaseMock: FirebaseMessaging {
// implemented functions go here
}
it says
This type has a constructor, and thus must be initialized here
If I try to initialize it like:
open class FirebaseMock: FirebaseMessaging() {
// implemented functions go here
}
it goes
Cannot access '<init>': it is private in 'FirebaseMessaging'
Which is true:
private FirebaseMessaging(Builder builder) {
...
All I want to do is make my stub class formally a subclass of FirebaseMessaging to use it as placeholder, that mocks the FirebaseMessaging-Functionality when the API keys are not present.
How can I just implement a non-abstract, non-interface class, that has a private constructor nonetheless.
My current solution is a wrapper, which works but is not as nice.
Mockito etc. does not seem like a good solution, since this is still in the productive code.

Inject httpcontext into custom attribute outside controller in .net core

I need to inject httpcontext into custom attribute that is used outside the controller. I found several solutions how to do it in controller, but my case is little tricky. Now I have following code in my PermissionController
[PermissionFilter(PermissionEnum.Permission, AccessLevelEnum.Create)] <-- it works perfectly
[HttpPost("users/{userId}")]
public async Task<IActionResult>
AssignPermissionToUser([FromBody] List<PermissionToVM> permissions, int userId)
{
await _permissionService.Assign(permissions); <-- .Assign() extension
//code goes here
}
In the method above there is a call of extension method .Assign. This method code is available below.
//[SecondPermissionFilter(PermissionEnum.Permission,
AccessLevelEnum.Create)] <-- here I check permissions but don't
know how to inject the httpcontext
public async Task Assign(List<PermissionToVM> permissions)
{
//code goes here
}
As mentioned in many websites I visited f.e. here https://dotnetcoretutorials.com/2017/01/05/accessing-httpcontext-asp-net-core/ injecting of httpcontext outside the controller can be done using IHttpContextAccessor. The problem is that I don't know how to use it without passing it into constructor. My custom attribute should be called as decorator [SecondPermissionFilter(PermissionEnum.Permission, AccessLevelEnum.Create)] when only permission settings should be passed, so there is no any reference to httpcontextaccessor.
Is this even possible? If not, there is maybe another way to do this?
EDIT: Here is the code of SecondPermissionFilter class:
public sealed class SecondPermissionFilterAttribute : Attribute
{
private readonly PermissionEnum _requestedPermission;
private readonly IEnumerable<AccessLevelEnum> _accessLevelCollection;
private readonly IHttpContextAccessor _contextAccessor; //<-- how to inject?
public PermissionFilterAttribute(PermissionEnum requestedPermission, params AccessLevelEnum[] accessLevelCollection)
{
_requestedPermission = requestedPermission;
_accessLevelCollection = accessLevelCollection;
}
}
What you are after is something called Property Injection. As per the official docs this is not something that is supported out of the box by the .NET Core DI Container.
You can however use a third party library such as Ninject or Autofac - both of which are available via NuGet.
In my opinion the Ninject syntax is nicer, however as noted in this answer, and this answer property injection itself is considered bad practice. So if possible I would try to avoid it.
So you should instead use one of the three methods specified by the filter documentation, this answer breaks things down a bit more.
Edit
This answer deals specificically with Attribute injection, the second answer looks to achieve this without external dependencies.

How to correctly dispose objects registered with Autofac

I've implemented Unit of Work/Repository pattern, as described here, but I'm also using autofac and constructor injection, so I registered UnitOfWork and DbContext (PsyProfContext) class like this:
builder.Register(context => new PsyProfContext()).InstancePerHttpRequest();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerHttpRequest();
And everything works great!
Except for one thing: I'm also using enterprise library logging block, and I have implemented CustomTraceListener which is using Entity Framework to write log entry into the database.
My controller looks like this (it is empty because at the moment I just tried to verify if all the things (IoC, logging, entity framework) are working):
public class HomeController : Controller
{
private readonly UnitOfWork unitOfWork;
public HomeController(IUnitOfWork unitOfWork)
{
this.unitOfWork = (UnitOfWork) unitOfWork;
}
//
// GET: /Home/
public ActionResult Index()
{
throw new HttpException();
return View();
}
protected override void Dispose(bool disposing)
{
unitOfWork.Dispose();
base.Dispose(disposing);
}
}
And in the Write method of the CustomTraceListener class, I've tried to Resolve UnitOfWork:
DependencyResolver.Current.GetService<IUnitOfWork>() as UnitOfWork;
But I get an instance which is already disposed! so I've put some breakpoints and found out that Dispose method of the controller is called before the Write method of the CustomTraceListener class, so in the end I didn't found other solution than using DbContext (PsyProfContext) directly:
public override void Write(object o)
{
using (var conext = new PsyProfContext())
{
var customLogEntry = o as CustomLogEntry;
if (customLogEntry != null)
{
var logEntry = new LogEntry
{
//a bunch of properties
};
conext.Exceptions.Add(logEntry);
conext.SaveChanges();
}
}
}
But I don't like this solution! What's the point to use UnitOfWork and Repository pattern if you access DbContext object directly. Or what's the point in using DI in project if you create a registered object manually in some cases.
So I wanted to hear your opinion, about how to deal with this kind of situations? Is my current implementation fine, or it is definitely wrong and I should think about another one.
Any help will be greatly appreciated and any ideas are welcome!
It looks like you may have a couple of problems.
First, if you're manually disposing the unit of work object in your controller, your controller should take an Owned<IUnitOfWork> in the constructor. When the request lifetime is disposed it will automatically dispose of any IDisposable components - including the controller and any resolved dependencies - unless you specify somehow that you're going to take over ownership of the lifetime. You can do that by using Owned<T>.
public class HomeController : Controller
{
Owned<IUnitOfWork> _uow;
public HomeController(Owned<IUnitOfWork> uow)
{
this._uow = uow;
}
protected override void Dispose(bool disposing)
{
if(disposing)
{
this._uow.Dispose();
}
base.Dispose(disposing);
}
}
(Note a minor logic fix in the Dispose override there - you need to check the value of disposing so you don't double-dispose your unit of work.)
Alternatively, you could register your units of work as ExternallyOwned, like
builder
.RegisterType<UnitOfWork>()
.As<IUnitOfWork>()
.ExternallyOwned()
.InstancePerHttpRequest();
ExternallyOwned also tells Autofac that you'll take control of disposal. In that case, your controller will look like it does already. (Generally I like to just let Autofac do the work, though, and not take ownership if I can avoid it.)
In fact, looking at the way things are set up, you might be able to avoid the disposal problem altogether if you let Autofac do the disposal for you - the call to DependencyResolver would return the unit of work that isn't disposed yet and it'd be OK.
If that doesn't fix it... you may want to add some detail to your question. I see where your controller is using the unit of work class, but I don't see where it logs anything, nor do I see anything in the listener implementation that's using the unit of work.
(Also, as noted in the first comment on your question, in the constructor of your controller you shouldn't be casting your service from IUnitOfWork to UnitOfWork - that's breaking the abstraction that the interface was offering in the first place.)

How to decorate interfaces bound to more than one concrete type with Ninject

So, I have a message bus that instantiates message handlers through Ninject. I'd like to decorate my handlers with cross cutting concerns such as logging, transaction management, etc.
I setup my bindings like so:
kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>()
.WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>));
Which works fantastically whenever I have a single handler of a specific message type. However, when I have more than one handler defined:
kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>()
.WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind<IMessageHandler<int>>().To<IntHandlerTwo>()
.WhenInjectedInto(typeof(HandlerDecorator<>));
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>));
Ninject will find and inject the decorator to the message bus, and then attempt unsuccessfully to inject both handlers into the decorator constructor.
public HandlerDecorator(IMessageHandler<T> handler)
You may be thinking, why don't I just modify my decorator to accept the list of handlers? I thought about this, but that defeats the purpose of the handler. I want to be able to easily chain multiple decorators together transparently. Each instance of IMessageHandler<T> should get an entirely new chain of handlers.
I've published an example test library on GitHub that should illustrate what I'm talking about here.
Is there any way to do this in Ninject?
Use
kernel.Bind<IMessageHandler<int>>().To<IntHandlerOne>().WhenParentNamed("One");
kernel.Bind<IMessageHandler<int>>().To<IntHandlerTwo>().WhenParentNamed("Two");
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>)).Named("One");
kernel.Bind(typeof(IMessageHandler<>)).To(typeof(HandlerDecorator<>)).Named("Two");
Also be aware that most of the Bus Frameworks have some way to do decorations for message handlers. May have a look there first.
You should wrap those handlers in a composite:
public class CompositeMessageHandler<T> : IMessageHandler<T>
{
private readonly IEnumerable<IMessageHandler<T>> handlers;
CompositeMessageHandler(IEnumerable<IMessageHandler<T>> handlers)
{
this.handlers = handlers;
}
public void Handle(T message)
{
foreach (var handler in this.handlers)
{
handler.Handle(message);
}
}
}
This composite can again be injected into your decorator. Or perhaps you should do it the other way around: Wrap each handler with a decorator and wrap those into the composite.
I'm not sure how to register this with Ninject though.

How do you use method injection with Ninject?

I have a class which needs to use an IRepository for one method in it's class.
Ideally, I would like to avoid having to resolve this dependency into the class's constructor, and so I found method level injection in Ninject and was wondering how this works?
I understand how to set it up. What I'm confused about is how to call it?
Example:
class SomeClassThatUsesRepository
{
[Inject]
public void QueryForSomeStuff(IRepository repository)
{
//do some stuff
}
}
My problem is how do I call this method without specifying an IRepository?
var someClass = Kernel.Resolve<SomeClassThatUsesRepository>();
would work if I was using the constructor, but I want to call a method.
How do I call a method using Ninject method injection?
I'm afraid method injection doesn't work this way - it's just one of the ways to inject dependencies into an object during its construction (you can inject your dependencies through constructor parameters, through properties, fields or methods). Method injection is useful if your class takes its dependencies by Java-style setter methods like
public void SetRepository(IRepository repository) { ... }
If it is marked with [Inject] attribute, you don't need to call this methods directly, it is to be called by Ninject during the initialization to pass the IRepository object into your resolved object.
So I believe your QueryForSomeStuff method is being called when you resove your SomeClassThatUsesRepository.
Confirmed that method injection doesn't work as intended. Got a custom MVC attribute class and wanted to use an injected object inside it. Did not pass it
into the constructor and added method
[Ninject.Inject]
public void ResolveDI(ISettingStore store)
{
ConfigHelper = store;
}
This method was never called and ConfigHelper was null when the attribute's OnActionExecuting was called.