{"id":12038,"date":"2025-11-29T16:10:59","date_gmt":"2025-11-29T16:10:59","guid":{"rendered":"https:\/\/putridparrot.com\/blog\/?p=12038"},"modified":"2025-11-29T16:10:59","modified_gmt":"2025-11-29T16:10:59","slug":"different-ways-of-working-with-the-httpclient","status":"publish","type":"post","link":"https:\/\/putridparrot.com\/blog\/different-ways-of-working-with-the-httpclient\/","title":{"rendered":"Different ways of working with the HttpClient"},"content":{"rendered":"<p>A few years back I wrote the post <a href=\"https:\/\/putridparrot.com\/blog\/net-httpclient-the-correct-way-to-use-it\/\" target=\"_blank\">.NET HttpClient \u2013 the correct way to use it<\/a>. <\/p>\n<p>I wanted to extend this discussion to the other ways of using\/instantiating your HttpClient. <\/p>\n<p>We&#8217;ll look at this from the view of the way we&#8217;d usually configure things for ASP.NET but these are not limited to ASP.NET.<\/p>\n<p><strong>IHttpClientFactory<\/strong><\/p>\n<p>Instead of passing an HttpClient to a class (such as a controller) we might prefer to use the IHttpClientFactory. This allows us to inject the factory and create an instance of an HttpClient using the method CreateClient, for example in our Program.cs<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nbuilder.Services.AddHttpClient();\r\n<\/pre>\n<p>then in our code which uses the IHttpClientFactory<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class ExternalService(IHttpClientFactory httpClientFactory)\r\n{\r\n   public Task LoadData()\r\n   {\r\n      var httpClient = httpClientFactory.CreateClient();\r\n      \/\/ use the httpClient as usual\r\n   }\r\n}\r\n<\/pre>\n<p>This might not seem that much of an advancement from passing around HttpClient&#8217;s. <\/p>\n<p>Where this is really useful is in allowing us to configure our HttpClient, such as base address, timeouts etc. In this situation we can use &#8220;named&#8221; clients. We&#8217;d assign a name to the client such as<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nbuilder.Services.AddHttpClient(&quot;external&quot;, client =&gt; {\r\n  client.BaseAddress = new Uri(&quot;https:\/\/some_url&quot;);\r\n  client.Timeout = TimeSpan.FromMinutes(3);\r\n});\r\n<\/pre>\n<p>Now in usage we&#8217;d write the following<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nvar httpClient = httpClientFactory.CreateClient(&quot;external&quot;);\r\n<\/pre>\n<p>We can now configured multiple clients with different names for use in different scenarios. With can also add policy and message handlers, for example<\/p>\n<pre class=\"brush: plain; title: ; notranslate\" title=\"\">\r\nbuilder.Services.AddHttpClient(&quot;external&quot;, client =&gt; {\r\n  \/\/ configuration for the client\r\n}).\r\nAddHttpMessageHandler&lt;SomeMessageHandler&gt;()\r\n.AddPolicyHandler(SomePolicy());\r\n<\/pre>\n<p><strong>Strongly Typed Client<\/strong><\/p>\n<p>Typed or Strongly Typed clients is another way of using the HttpClient, weirdly this looks much more like our old way of passing HttpClient&#8217;s around.<\/p>\n<p>We create a class specific to the HttpClient usage, and have an HttpClient parameter on the constructor, for example<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\npublic class ExternalHttpClient : IExternalHttpClient\r\n{\r\n  private readonly HttpClient _httpClient;\r\n\r\n  public ExternalHttpClient(HttpClient httpClient)\r\n  {\r\n    _httpClient = httpClient;\r\n    _httpClient.BaseAddress = new Uri(&quot;https:\/\/some_url&quot;);\r\n    _httpClient.Timeout = TimeSpan.FromMinutes(3);\r\n  }\r\n\r\n  public Task&lt;SomeData&gt; GetDataAsync()\r\n  {\r\n     \/\/ use _hhtpClient as usual\r\n  }\r\n}\r\n<\/pre>\n<p>We&#8217;d now need to add the client to the dependency injection in Program.cs using<\/p>\n<pre class=\"brush: csharp; title: ; notranslate\" title=\"\">\r\nbuilde.Services.AddHttpClient&lt;IExternalHttpClient, ExternalHttpClient&gt;();\r\n<\/pre>\n<p><strong>Conclusions<\/strong><\/p>\n<p>The first question might be, why use strongly typed HttpClient&#8217;s over IHttpClientFactory. The most obvious response is that it gives a clean design, i.e. we don&#8217;t use &#8220;magic strings&#8221; we know which client does what as it includes the methods to call the endpoints for the developer. Essentially it encapsulates our HttpClient usage for a specific endpoint. It also gives us a cleaner way of testing our code by allowing us to mock the interface only (not having to mock an IHttpClientFactory etc.).<\/p>\n<p>However the IHttpClientFactory way of working gives us central place where we&#8217;d generally have all our clients declared and configured, named clients allow us to switch between clients easily using the name, it also gives great integrations for things like Polly.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A few years back I wrote the post .NET HttpClient \u2013 the correct way to use it. I wanted to extend this discussion to the other ways of using\/instantiating your HttpClient. We&#8217;ll look at this from the view of the way we&#8217;d usually configure things for ASP.NET but these are not limited to ASP.NET. IHttpClientFactory [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[49,200,3],"tags":[],"class_list":["post-12038","post","type-post","status-publish","format-standard","hentry","category-net","category-asp-net-core","category-c"],"jetpack_sharing_enabled":true,"jetpack_featured_media_url":"","_links":{"self":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/12038","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/comments?post=12038"}],"version-history":[{"count":5,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/12038\/revisions"}],"predecessor-version":[{"id":12043,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/posts\/12038\/revisions\/12043"}],"wp:attachment":[{"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/media?parent=12038"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/categories?post=12038"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/putridparrot.com\/blog\/wp-json\/wp\/v2\/tags?post=12038"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}