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
Using HttpClientFactory without dependency injection #28385
Comments
The answer to this really depends what you expect to get out of using the client factory. I get asked this question a lot, and the answer depends on a lot more details about what you want to accomplish. It sounds like you might have a few different scenarios so I'm providing a lot of information with the hopes that it's helpful. If you are building a library that you plan to distribute, I would strongly suggest that you don't take a dependency on If you are building a non-ASP.NET-Core application, consider using If you are building a non-ASP.NET-Core application and you really don't want to use A. I want an opinionated builder abstraction for configuring HttpClientFactory. If you are in category A then I have to explain that DI and Based on the information you provided, I'm guessing you fall into category B. If you are on .NET Core - you should use a single If you are on .NET Framework - you should use a single The good news for anyone interested in connection management is that .NET now has reasonable behavior on Linux (as of 2.1 and |
I've logged a doc issue to clear this up further. dotnet/AspNetCore.Docs#11882 |
Thank you for the detailed answer (and that doc request), that is going to help a lot! In my case, I’m somewhere between A and B actually. The client library I am working on is mostly targeted to ASP.NET Core applications, so I have a helper extension method on the service collection that just adds all the clients as typed clients using the HttpClientFactory (using a custom options object to configure a few parameters). That is working just fine the way it is. However, I now have the requirement to use this in a legacy ASP.NET application that uses Autofac as DI container. So I cannot really use any M.E.DI-specific stuff, and I certainly don’t want to bring all the stuff into that project just to use the HttpClientFactory. Ideally, what I would like to do is to set up a HttpClientFactory, configure a few clients and then have something I can call to create a factory method that I then register with the existing DI container. What you say makes sense though; the factory makes heavy use of DI and options, so using it without it would be really difficult. In my case, the various clients each have different
It would be really nice if there was some guidance along with the docs on what would be good defaults for setting up a HttpClient. |
Sure you can, in this mode, think of M.E.DI stuff as an implementation detail for how to get an IHttpClientFactory instance. The other features though, rely on this internal detail in order to do more complex things (like typed clients etc). Alternatively, if you really wanted to try to integrate the 2 things (autofac and the HttpClientFactory), you can use the ServiceCollection as the configuration API for the HttpClient and use Autofac.Extensions.DependencyInjection to wire it up to your existing autofac container: public class MyTypedClient
{
public MyTypedClient(HttpClient client)
{
}
}
public class Program
{
public static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddHttpClient()
.AddHttpClient<MyTypedClient>();
var containerBuilder = new ContainerBuilder();
containerBuilder.Populate(services);
var container = containerBuilder.Build();
var factory = container.Resolve<IHttpClientFactory>();
var typedClient = container.Resolve<MyTypedClient>();
}
}
+1 |
Hey everyone I've made a fork to address this issue. |
I'd like to stress out that using the DI container for absolutely everything is not the best example of design. Insisting that all developers need to use the container for things like HTTP client factory, in-memory cache, distributed cache, logging and so on, creates impediments for developers that would otherwise avoid using DI containers altogether. I personally prefer to construct my dependency tree in the There's was an issue dotnet/extensions#615 for using |
I also feel like this seems like a strange way to strongarm people out of using other DI containers. I maintain Xamarin Forms projects that predate the M.E.DI stuff. One uses TinyIoC because it chose the FreshMVVM framework. The other uses AutoFac. It would be a PITA for me to rework them to use the Microsoft DI container. I shouldn't have to in order to use HttpClient. In the AutoFac project, I'd like to reuse a REST utility someone else made for interacting with an internal web service. That utility was written in an ASP .NET Core environment so it already expects me to give it an HttpClient. So he's using the Web Host container and gets all the stuff I want for free. I don't see good guidance for how to configure AutoFac to do the same thing your DI does. I do see a kind of janky path to set up the M.E.DI container, then somehow convert that to AutoFac. That feels ridiculous. I get that HttpClientFactory is opinionated, but I don't think part of that opinion should be "your app must use Microsoft DI". Especially in the Xamarin context, I'm bewildered. I've scanned a few articles and issues related to this and I can't tell if I should or shouldn't be using IHttpClientFactory at all. Some seem to suggest I should just set I don't see a clear message for how devs outside of ASP .NET Core are supposed to use HttpClient. I thought when I found this library it would be the clear message. But it looks like even within this library, I see confusing comments that imply outside of ASP .NET Core I might not even want to use HttpClientFactory. Even if that was the wrong read, I don't see an explanation for what the magic inside M.E.DI is so I can realize it with a different DI container (or no container at all.) If Generic Host container isn't suitable for all platforms, where is the documentation that outlines its limitations and explains, for every Microsoft-supported platform, what the best practice for using HttpClient is? I shouldn't have to read half a dozen blogs to understand such a crucial type, it should be explained by MS. |
Incidentally AutoFac has MS DI integration - I think it boils down to a one-liner ( That said, we went ahead with AutoFac for many internal projects but are struggling to see any advantage to it considering all MS packages use |
I have a net core unit test project without DI and having a static |
You are absolutely right that dependency injection is not everything I need. Sometimes dependency injection is more cumbersome and increases my workload. It seems useful but it is meaningless, 666 |
Is it possible to use the app.ApplicationServices.GetService() in the Configure method to get the IHttpClientFactory, then assign it to public static, and then globally. |
I'm sure you can do this, and I'm sure that the code will work. However you're baking in a dependency on a global static. Do you really want to do that? Will you ever want to test any of that code? |
Thank you for your help. Our code is converted from asp.net. Not only httpclient needs to be called in the controller, but also in many classes. It's not easy to rely on the injection method, so I made a global static, maybe I didn't find a better way. |
Which NuGet, assembly and namespace is this mythical HttpClientFactory class located in? I can't find it anywhere... |
@davidfowl Why not to extract |
@rynowak I don’t need ‘an alternative’, I just want reusable abstraction, so my library works nice and has stable interface both in the context of ASP.NET Core and in a stand-alone application. |
Hi @rynowak, Let me question you why |
SocketsHttpHandler is part of .NET Core, I'm not sure if there's a technical reason why it's not in netstandard2.1. I'd suggest asking at dotnet/standard or dotnet/runtime. |
@rynowak we're seeing .NET Core racing ahead without waiting for other platforms to catch up. This is dangerous and devalues .NET Standard. Xamarin and UWP both need the same APIs and further bifurcation is going to lead to more fragmentation of the .NET ecosystem. |
@rynowak Is there a recommended value for |
It depend on your scenario. I'd suggest starting with a value like 15 minutes and if that gives you good results, leave it. |
The tight coupling between the new Currently I would try to get the instance of |
@yanxiaodi . Exactly. All that needs to be done is to give |
@rynowak does configuring SocketsHttpHandler.PooledConnectionTimeout solve DNS issue as mentioned here https://docs.microsoft.com/en-us/dotnet/architecture/microservices/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests#issues-with-the-original-httpclient-class-available-in-net-core ? I want exactly all benefits of HttpClientFactory but without DI in a normal console app (.NET Core 3.1). |
I am curious about how does Azure key vault work when we add it as a configuration provider during the Azure SDK has a concept, Is the |
It is a sibling. The AzureSDK team built their own primitive for outgoing http requests. The equivalent in the BCL is a MessageHandler |
For what it's worth, I wrote my own version of this that implements @rynowak 's recommended behavior above for .NET Core and .NET Standard. It doesn't use the exact interface because it's only available if you pull in a ton of ASP.NET dependencies but is pretty easy to use and I'm happy to make changes if needed. |
@rynowak , @davidfowl : For targeting .Net framework, is this a good solution to use under heavy load? What happens when the ServicePoint.ConnectionLeaseTimeout expires? |
This issue should not be closed. I don't see the proper solution after 2 years. |
That WebRequest-HttpWebRequest / HttpClient problem makes me think I've chosen wrong platform to learn and work with 10 years ago and all my life gone wrong. |
@rynowak please re-open this issue, @msftbot closed this when it shouldn't have. |
@bugproof According to the official Microsoft Docs, here:
You can use // Used throughout your application (i.e. app lifetime)
using var httpSocketHandler = new SocketsHttpHandler();
using var httpClient = new HttpClient(httpSocketHandler);
using var response = await httpClient.GetAsync(@"https://www.google.com"); |
@mary-perret-1986 that code snippet would need to be tweaked slightly to achieve the stated goal. |
@ericsampson Would you mind elaborating on this? |
@mary-perret-1986 |
As unrealistic as it may sound, I would suggest you to backport whatever you can to make it compliant with the version of the framework you're forced to use. (I thought we were talking about .NET Core 3.x and .NET 5+, hence the reason I didn't really get why there was an issue for you). |
@mary-perret-1986 Doesn't it make more sense to make the default empty constructor of |
See? There's always something about Ideally, the constructor of |
No-one is saying that
My understanding is Ryan meant each separate consumer of a |
@Jehoel @stevejgordon This article mentions that Sigh, I just wish Microsoft could make the |
I don't understand why you think you need it. Are you managing different settings per handler? If not then you don't need it. |
I would believe that creating multiple HttpClients - one for every consuming service - would each use their own instance of |
Then use the same singleton instance? |
If this is how |
Sure store it in your own static. There are obviously much more advanced use cases but the default should be a single instance used by your app until further notice |
Just storing a singleton SocketsHttpHandler would mean a shared cookie container by default no? Which is the kind of foot gun that leads to security issues when sessions are shared between clients unexpectedly. |
I believe cookies is off by default, so you would be opting into that footgun. Also I hope your API are using bearer tokens (though that's a separate discussion). |
So cookies are shared between different HttpClients if they use the same message handler? |
The cookie container is per handler instance. Like I said before, if you need to vary settings or state per handler then you need to manage multiple http clients. Otherwise use a single one |
The The default value for this param can't be changed unfortunately, due to backwards compatiblity requirements. using var httpSocketHandler = new SocketsHttpHandler(){ PooledConnectionLifetime = TimeSpan.FromMinutes(3) };
... |
@davidfowl And if I have varying settings on the handler? Would having multiple |
The connection management is coupled to the |
So if I understand things correctly... Example 1:
|
@Jehoel, FWIW if you want to see how someone has handled these issues, you can take a look at the Azure SDK. IIRC they've dealt with this. I'm definitely not saying that it shouldn't be easier OOTB, but at least as a reference… |
Is there any way to consume the
HttpClientFactory
without using dependency injection, or more precisely without using M.E.DI?I am creating a client library for which I want to make use of HttpClientFactory but I am going to use this library also in a legacy project that does not not have a M.E.DI-compatible DI.
Ideally, I would just new up a
DefaultHttpClientFactory
and consume that directly but since the factory itself is internal, this is not possible.Why is the
HttpClientFactory
internal and is there any way to consume it explicitly without using DI?The text was updated successfully, but these errors were encountered: