Hidden Dependency Injection Limits with Autofac in ASP.NET Core
Dependency injection is a powerful pattern that we can use in software development. ASP.NET Core comes with the IServiceCollection functionality built in to give us this kind of capability. However, we do have other tools, such as Autofac, that can enable us to do more powerful things with our dependencies.
In this video, I'll explore the trade-offs of using Autofac in the recommended way for setting up your application. For many people, this pattern will work very well. However, as someone who builds plugin architectures, there are a few limiting factors that I need to work around!
View Transcript
there are many different approaches that we can take to dependency injection inside of asp.net core personally one of my favorites aside from just the I service collection that's built in is to use a nougat package that's called autofac but even when it comes to using autofac there's many different approaches that we can go with hi my name is Nick centino and I'm a principal software engineering manager at Microsoft in this video I want to go over the most common way that we can set up autofac to use inside of an asp.net core application and talk about what the pros and the cons are of it I felt like this was important to go over because if you don't understand what you get and what you're missing by doing this approach you can't make informed decisions and you might get tripped up a little bit later
when you're looking for some behavior that you don't have access to a quick reminder to subscribe to the channel if you enjoy this kind of content and check out my pin comment for my courses on D Trin so I wanted to start this off by mentioning that not long ago I put together this quick blog article to address exactly one of the challenges with working with autofac and that's because I was setting up another application and starting from scratch I kept getting tripped up with the best way to set up the container now is this the best way or is this just the common way right and the reality is that this is just the common way this is how they explain to you how to configure the container so what you end up doing is skipping some of the Legacy stuff that they used
to have it's marked as Obsolete and then you'd be able to jump right into using these two lines to be able to configure your host or you could do it all in one line so this is the common pattern and we're going to walk through that in this video to see what you get and what you're missing I felt like one of the best ways to get started here was using the sample weather application because I don't need to come up with some totally contrived thing you can go make this on your own and see how it all works so if I Collapse some of the autofact stuff and we just look at what we have access to right we have the Builder that's going to be creating our web application you'll see this oneliner that comes from the blog post I mentioned that's basically
use service provider Factory and then we configure it with autofax so we'll look at that in more detail but then later we're going to build the application off of the web application Builder and then this is just to have https not really important for this demo and then from there we add our route onto the application I've gone ahead and extended this because I wanted to make sure that we could play with some things that would show us what we can and cannot do with this type of dependency injection so this is the sample weather app but I've gone ahead and I've added a few parameters onto our minimal API and I'm going to walk through what those do in just a moment otherwise the rest of this is basically the same type of thing the weather forecast uh record that we have is the
return type but these three new records are or I guess these are classes these are going to be slightly interesting because they have to use some type of dependency injection so the the thing that I want to show you if I scroll back up is if we go to the minimal API these are things that we can resolve from Services as this attribute suggests and that means that that the dependency injection framework when this route is hit by a caller will look to be able to provide these as parameters into our method I just wanted to call out that this from Services attribute is not required for this to work but we're going to see some things that make this a little bit interesting and from services will make this a little bit more clear once we encounter that going back down these are three
different types of dependencies that I put together and you might be saying well why would you ever have these and the reality is that I might not need them on something like our minimal API here but this is going to show us a couple of examples where we can and cannot resolve dependencies and the reason I picked these three is because I have situations for creating plug-in architectures in asp.net core that will be follow-up content this is really the primer that I'm trying to build up to so in the future if you're trying to build asp.net core plugin archit textures this type of thing in my opinion will be extremely helpful for understanding how that works so when I go to build plugins and I'm hooking different things up I want to be able to have access to this web application Builder because I may
want to create plugins that can help configure the web app before it's built I have other situations where I need to use the uh application itself this doesn't need to be lazy this was me trying to play around and see if I could make autofac do the right thing so this does not need to be on here in fact we can go take that rate off and then this last one here dependency C is for the configuration for me this is really common that when I'm creating plugins or other features that use autofac or dependency injection in general I want to be able to access stuff that's in the configuration and that's because I'm basically setting things up in environment variables when I deploy and I want to read in that config for my feature these are three different things not these dependency a b
and c that I need but the uh the dependencies that they take in as these primary Constructor parameters so these are three things that I generally want and the reason that I put them on the minimal API is because there are situations where being able to have access to these is doable but not from the minimal API so there's basically like these four things that I want to put together right these dependencies down here that I just walked through and whether or not we can access them on the minimal API now that we have that covered I'm going to go back over to this part of the code where we can see how we're setting up our container and I wanted to show that the first thing we're doing is we're registering the actual uh web application Builder so not to be confused with the
container Builder there's two different Builder patterns going on here so we put the web application Builder onto the autofac container Builder little bit confusing um then from there we are going to take the configuration off of the web application Builder and you'll see that the syntax I'm using here I'm just trying to resolve the web application Builder technically I don't have to do that I could just basically use Builder right here because we already have access to it again this is a little bit of proof that I can go resolve the web application Builder if something goes and asks for the configuration so far if you're paying attention you'll realize that these are two different things that I have on dependency a b and c that we just looked at at the bottom of this file right now the other three things that we're going
to register onto this container are dependency a b and c themselves these are just going to be single instance because they're just being used for references to these different services that I want we looked at registering these three things and then we said these are two examples of things we want but what about the actual web application itself not the Builder but the thing that gets built from it well that's down here so if I go run this one of the challenges that we're about to see is that we don't have access to the web application that was built it's never been added to the container so let me go ahead and run this and when the minimal API is hit so when we go to access that weather forecast route we'll see that we get an exception that comes up and there we go
right in front of our faces here it says dependency B can't be invoked with available Services it can't find a web application that's exactly what I was just saying that's not been put onto the container right so so far that's one sticky issue so if I expand this little comment here I have a fix me here saying hey look we can't put the web application onto the container that means we can't have anything that requires it as a dependency so this is one limitation now you might say okay well maybe we just figure out a way to get that onto the container right cool before I jump over to how we do that I wanted to call out that when it comes to to resolving dependencies these get resolved in order so we were able to prove that dependency a was resolved okay because it
ended up failing on dependency B it didn't fail immediately on dependency a and just to kind of prove what can be resolved by default I'm going to put these in a different order and we'll see if B is still the only one that comes up and it's still is so that means dependency a and dependency C out of the box work for us right that means we get the configuration that's accessible and we get the web application Builder that's also accessible web application itself is the only one of these three that is not accessible I'll pause there because if you're Building Systems and you want to be able to have a plug-in architecture let's say or just have other things that can be able to access these things off of the autofac container you're doing okay if you don't need the web application if you
just need the config and the web application Builder this will work perfectly fine for you we can look at this bit of coat here and we can try to see if that's even possible for us so if I go remove this comment what this might look like is we say okay we have this container Builder let's go do what we were doing with the other things right let's go use this registration method we're going to ask for the Builder and we already have that we prove that we could do that by accessing the configuration so let's go ask the Builder Let's go ask for the reference of it and then call build so we can go build the application right so we're basically taking these lines of code from down below oh that's a spoiler don't look at that down below taking these lines right
and trying to put that on the container but the reason that this doesn't work and I just want to explain this because the life cycle of this is a little bit weird is that in theory this would put a web application onto the container for us so that would go onto the autofac container but the only way that this resolution up happening is because we asked the web application Builder itself to go build it so we need to call this method in order to even have these different registrations take effect which seems kind of weird now that doesn't work because it's almost like a chicken in the egg problem we need to call this basically down here in order for all of these registrations to start getting resolved which means then later on we would go do this again and that's the tricky part we
don't have the reference to the application we wanted to build we're essentially building a new one as we're trying to build the first call to it again little confusing it's a Chicken and the Egg problem so this does not work we can't go ahead and do that unfortunately um let me go put that other comment back in so that doesn't work and I guess I'm going to expand this in just a moment but the idea here is so far we only have web application that we don't have access to you might be saying well Nick maybe I don't care about that right I already said if you had access to those two other things and that's all you needed you're essentially good to go at this point like you're you don't need to be you know trying to figure out how to get access to
this web application if you don't need it one of the situations I mentioned plugins that I want to be able to use this is that I like having my routes be pulled into what I would call like vertical slices features so if I'm doing like a plug-in approach which really helps me structure for vertical slices that means that I can't register routes at least by going onto the application itself and doing map get or map post whatever it happens to be so I really need access to this web application in order to have features or plugins that can dynamically register their routes could this be done in a different way the answer is most certainly there's going to be workarounds for this but if I want access to the web application itself how might I go about that okay now we're going to expand this
last comment because I want to show you that this is how it would normally look for me if I were using autofac with a plug-in and basically all that I'm doing is I'm pulling the code we just looked at it's the exact same right I've just copied and pasted it into another uh registration this one's going to be a build call back so it's a little bit different this just gets called Web the Builder is building so it doesn't have to rely on someone else to resolve it it will go run automatically when the container is built in the future we're going to see how we're going to move away from this it's not the pattern that I like using in fact to me this kind of thing is a bit of an anti pattern for the most part with working with autofac but this
is what we would want to do we would want to say hey container get me the web application because once I have access to it I want to go Reg register a route in this given example with the weather uh forecast route this is overkill we don't need it it's one route we're not making a plugin for it but if I wanted to go build plugins with different routes this is the kind of code that I would want to pull into those individual plugins the point that I'm trying to get at here is this indeed will not work and I think if I go run this we'll see that in just a moment as long as I didn't miss any compile errors and I didn't but you'll see right it's running running the build callback and it's telling us you can't do this it's the
same problem that we saw on the minimal API itself when it was being accessed but you can't do this because web application was never put onto the container okay so that was a whole lot of what you can't do with this but I should cover the things that you can do and I did show you what was happening but what we're able to do with this is we can have access to services from autofac on the minimal apis that's actually very beneficial because if you like writing minimal apis and you like that syntax using this approach using the service provider Factory you can use things registered to autofact directly on your minimal API calls that is a big benefit as I showed you we also have access to the web application Builder so again if you wanted to make plugins or other features that could
leverage that you have access the same thing is said with the IE configuration so if you want environment variables or some other type of configuration you wanted to pass into your asp.net core application using this approach you do have access to that as well whether it's for features or plugins I would say for most people most situations this is totally cool totally acceptable not a whole lot to worry about but for me I'm building plug-in based applications and this is kind of limiting for some of the things that I like to do so what if we didn't use this Approach at all what if we wanted to use autofact still but we didn't want to use this way we wanted to just make our own container Builder and see how we could set things up well in this video that I'll show you next you
can see how that behaves and what you get and what you don't thanks and I'll see you next time
Frequently Asked Questions
What is Autofac and why should I use it for dependency injection in ASP.NET Core?
Autofac is a NuGet package that provides an alternative approach to dependency injection in ASP.NET Core applications. I personally prefer it because it offers more flexibility and features compared to the built-in IServiceCollection. However, it's important to understand the common setup and its limitations to make informed decisions.
What are the limitations of using Autofac with minimal APIs in ASP.NET Core?
One of the main limitations I encountered is that the web application itself is not accessible from the Autofac container. This means that if you need to register routes dynamically or use certain features that rely on the web application, you might run into issues. While you can access the web application Builder and configuration, the actual web application must be handled differently.
How can I resolve dependencies in a minimal API using Autofac?
You can resolve dependencies in a minimal API by using the 'FromServices' attribute, which allows the dependency injection framework to provide the necessary services when a route is hit. This is beneficial because it enables you to leverage services registered in Autofac directly within your minimal API calls.
These FAQs were generated by AI from the video transcript.