What is the equivalent of DefaultControllerFactory in Web API? - c#

We are trying to replace previous DefaultControllerFactory with new ASP.NET Web API to better handle REST/XML calls. Searching the web always pointed to implementating System.Web.Http.Dependencies.IDependencyResolver and then handling the GetService() and few other methods required by the interface.
However it seems to be caching the ApiController instance and any new controller, it does not seem to be resolving. Its difficult to provide all possible ApiController instances during startup due to performance issues.
DefaultControllerFactory allows providing controller instances and caches the "hit" entries, but throws errors when the an instane could not be delay loaded.
Are there are other overloads/controller factory methods that requires to be implemented?
Search did not yield any hits so far, but any pointers will be great. Thank you for your time.

It is IHttpControllerActivator implemented by DefaultHttpControllerActivator.
You may replaces it using:
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator),
new MyOwnActivatior());
Oops!
I meant IHttpControllerSelector!
It is IHttpControllerSelector implemented by DefaultHttpControllerSelector.
You may replaces it using:
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerSelector),
new MyOwnActivatior());

Related

How to ensure transient DI services are chained correctly

Okay, so more than anything I think I either have a terminology issue here or otherwise I need some help understanding why what I'm thinking of is not such a good idea. Unfortunately, I'm self-taught so often my terminology is wrong or old-fashioned. I've no problem accepting that some of the code I produce contains quite a few smells, but I want to understand what makes it smelly so that I can attack the most risky parts first.
I've been making some use of the DI functionality baked into .NET in recent years, mostly for injection of singletons into MVC controllers. I'm now trying to make better and more expansive use of DI, and especially to stamp out the remaining places where I've got business logic directly in actions on controllers.
So currently, I have no issue getting an ILogger<ControllerType> and a singleton of IDatabase (not really called that but you get the idea) injected into controllers. Within the controller constructor, I then create an instance of, for example, ReallyUsefulHelper that takes an ILogger and an IDatabase in it's own constructor. That's very handy, as then the logging from within ReallyUsefulHelper has the controller scope and it's clear in the log output as to which controller the call inside ReallyUsefulHelper came from.
I'm aware though that controllers themselves are transient (new instance for every request) and some of my services like ImportantButLessCommonlyUsedHelper might be a little expensive to instantiate, so I want to inject ReallyUsefulHelper transiently, and perhaps her cousin ImportantButLessCommonlyUsedHelper scoped. Of course, there's many more different such services across the application but you get the idea.
My question is - is there some way to have the controller's ILogger<T> instance injected into the IHelper instance during instantiation by the DI container? If so, what would this approach be called, so I can read more about it? If there's something wrong with this, what is it so that I can understand better? It seems clunky to me to pass an ILogger to each method in the IHelper that needs it which would otherwise get the job done. I have seen lower level libraries that provide a delegate for you to attach your ILogger.Log() method to but this also seems clunky and unnecessary for my purpose.

.NET Core 3.1 Web API - Inject multiple services of same interface

I have a API that is responsible for processing some documents that are posted to it. To do this I have a controller with endpoints for different file types such as "word", "excel", "image" etc.
This controller is injected with a service responsible for handling the processing.
private readonly IDocProcessor documentProcessor;
public MyController(IDocProcessor docProcessor)
{
documentProcessor = docProcessor;
}
This is all working perfectly, I now have the requirement to modify the processing, in just the "image" endpoint, due to a limitation in a third-party component.
So, what I want to do is write another service which implements IDocProcessor for images. It will not be used for the others, so will simply throw a NotImplementedException.
What I am struggling with is how I can inject both services into the controller? Or the best practice for doing this.
I have been reading through this question How to register multiple implementations of the same interface in Asp.Net Core? for some pointers, but some of the answers are few years old so wonder if there are new ways to achieve this?

Autofac - Decorate all components from a particular assembly

So I want to do some profiling on a bunch of controllers which inherit from System.Web.Http.ApiController. In the project that's doing the profiling, we're registering them with
builder.RegisterApiControllers(typeof(Web.Modules.AutofacModule).Assembly)
.As(type => new Autofac.Core.KeyedService("api", type));
Later on, I'm trying to register a decorator for each with
builder.RegisterDecorator<ApiController>(original => Decorate(original, profiler),
fromKey: "api");
where Decorate injects some profiling code via a DelegatingHandler and returns the original.
I can resolve the controllers just fine:
scope.ResolveKeyed<RegistrationController>("api");
but the profiling code is never invoked, nor is Decorate.
My first thought was that maybe I need to register the controller components as ApiController's, but dropping an .As<ApiController>() just below first snippet wasn't successful.
Any help would be super. This probably just boils down to my lack of Autofac-fu.
So I want to do some profiling on a bunch of controllers which inherit from System.Web.Http.ApiController.
This is impossible. This has nothing to do with Autofac, but with the way ASP.NET Web API is designed.
Even though Web API Controllers derive from a common base class, ASP.NET Web API requires the original controller type to be used. In other words, when it requests a HomeController from the IHttpControllerActivator, it expects that exact type (or a sub type), but not a sibling type (another ApiController derivative).
I think this limitation exists because Web API uses reflection to find the actual action methods. But when you return a decorator, those methods are gone, because a decorator applies composition instead of inheritance. This is very different from how ASP.NET MVC is designed. MVC actually does allow controllers to be decorated, as it always invokes the IController.Execute method. Implementation IController is therefore MVC's only requirement for controllers.
So even if you configure Autofac to wrap any ApiController derivatives in a Decorator, Web API simply won't let you.
The way to apply Cross-Cutting Concerns around the invocation of action methods in Web API is through the use of delegating handlers.

How to solve chicken-egg dependency resolution for MVC controller with Authorize attribute applied?

I have this situation where the fact that the user is not logged in is preventing the construction of my controller's dependencies.
[Authorize]
class MyController : Controller
{
public MyController(MyService service)
{
}
}
class MyService
{
public MyService()
{
// requires information which only
// becomes known after the user logs in
}
}
My question is: can I do something to cause the MVC framework to first look at the Authorize attribute and then resolve the controller instance?
The above would be much more preferable to me than either of the following:
Changing MyService to be able to handle being created before user log in
Injecting Func
Switching to service location
Ideally, I'd like to flip a switch in the MVC framework that says, "before you resolve the controller, check that you're actually going to use it and not toss it out due to lack of authorization and direct anyway..."
I have this situation where the fact that the user is not logged in is preventing the construction of my controller's dependencies.
That's the root of your problem.
// requires information which only becomes known after the user logs in
This means that the constructor of that service does too much. Constructors should not do more than store the incoming dependencies. This way you can compose object graphs with confidence.
The building of object graphs should in general be static. This means that the resolved object graph should not change based on runtime conditions (there are exceptions, but this is a good rule of thumb). It shouldn't matter whether or not a user is authorized or not, the service class should still be composed and injected. This means that authorization and loading of data is done at a later point in time; the moment that the request is actually executed (which is directly after the object graph is composed).
Your problem is that you don't really understand how the MVC Request pipeline works.
The first thing you have to realize is that Attributes are, in essence, designed to match up with identical events in the controller base class. There is an OnAuthorization method in Controller, and this is called either just before or just after the attributes OnAuthorization method is called.
So, in order for it to call both methods at roughly the same time, that means the Controller class must have been constructed to do so. What's more, a lot of other stuff goes on before Authorization filters, such as model binding, because your authorization filter may need information from the model to make its decision.
I suggest you check out this pipline chart.
https://www.simple-talk.com/dotnet/.net-framework/an-introduction-to-asp.net-mvc-extensibility/

C# HttpSelfHostServer can I regain control of Controller construction?

Due to limitations on the server side I need to build a self hosting web service in .NET...
I'm currently looking at HttpSelfHostServer but I'm very un-cool with it's magical construction of the controller, that seems to be, based on name alone and using only the default constructor.
For my tests I need to inject a value into the controller and using an IoC framework for this one usage where vanilla dependancy injection will suffice is over the top.
Is there any way I can do this with HttpSelfHostServer? or are there other, non-deprecated, self-hosting alternatives that give me control over my controller constructor calls.
The HttpSelfHostConfiguration instance that you need to provide to the HttpSelfHostServer constructor inherits the DependencyResolver property from the HttpConfiguration class. Hence, you can provide a custom dependency resolver as outlined here, for instance.
I was able to override IHttpControllerActivator in a unit test, I think it's similar to what you're trying to do.
e.g.
httpConfiguration.Services.Replace(typeof(IHttpControllerActivator),
Mock<IHttpControllerActivator>());
(there's more info. about services here)

Categories

Resources