{"id":1560,"date":"2020-08-19T09:00:40","date_gmt":"2020-08-19T16:00:40","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/cosmosdb\/?p=1560"},"modified":"2020-08-31T10:33:38","modified_gmt":"2020-08-31T17:33:38","slug":"httpclientfactory-cosmos-db-net-sdk","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/cosmosdb\/httpclientfactory-cosmos-db-net-sdk\/","title":{"rendered":"HttpClientFactory in the Azure Cosmos DB .NET SDK"},"content":{"rendered":"<p>You might already be familiar (and if not, you should) with this famous post called &#8220;<a href=\"https:\/\/aspnetmonsters.com\/2016\/08\/2016-08-27-httpclientwrong\/\" target=\"_blank\" rel=\"noopener noreferrer\">You&#8217;re using HttpClient wrong<\/a>&#8221; and how it is important to reuse connections across the lifetime of your application. Recently, the V3 .NET SDK has added a feature called <strong>HttpClientFactory<\/strong> as part of the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/microsoft.azure.cosmos.cosmosclientoptions.httpclientfactory\" target=\"_blank\" rel=\"noopener noreferrer\">CosmosClientOptions<\/a>, which is used to customize the client instance and enables HTTP connection sharing between the SDK client and other clients within the same application. How? Let&#8217;s see!<\/p>\n<h3>First things first<\/h3>\n<p>If you are reading this post, you either detected a scenario where your application is using a lot of connections (and it&#8217;s causing issues on your environment), or you are trying to optimize because, well, we all like when things are tidier.<\/p>\n<p>So the first thing you need to verify is that you only have <strong>one SDK client for the entire lifetime of the application<\/strong>. Dependency Injection frameworks make this very easy these days, if you use <a href=\"https:\/\/docs.microsoft.com\/aspnet\/core\/fundamentals\/dependency-injection\" target=\"_blank\" rel=\"noopener noreferrer\">ASP.NET Core<\/a> for example, it&#8217;s as simple as registering it when configuring your services:<\/p>\n<p>https:\/\/gist.github.com\/ealsur\/ea583996ec32ee0cbcc4683db6c3b42a<\/p>\n<p>If you don&#8217;t use Dependency Injection frameworks, you could opt for having static variables. Just make sure that whatever you do, there is only a single instance (be careful with Repository Patterns that create client instances internally!).<\/p>\n<h3>This sounds similar to IHttpClientFactory in .NET<\/h3>\n<p>And the reason for that is because the HttpClientFactory feature was initially designed to work alongside the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/architecture\/microservices\/implement-resilient-applications\/use-httpclientfactory-to-implement-resilient-http-requests\" target=\"_blank\" rel=\"noopener noreferrer\">IHttpClientFactory provided by ASP.NET Core<\/a>. This allows the application to centralize the creation of HttpClients and, therefore, allow consumers to reuse already existing connections.\u00a0<\/p>\n<p>When designing the feature, we aligned it with the <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/system.net.http.ihttpclientfactory.createclient\" target=\"_blank\" rel=\"noopener noreferrer\">IHttpClientFactory.CreateClient<\/a> method, to make it easier for developers to leverage.<\/p>\n<p>https:\/\/gist.github.com\/ealsur\/491bbbe78e5349d6f0ff3bb3fd051515<\/p>\n<h3>Blazor Wasm support<\/h3>\n<p>In Blazor Wasm applications, <a href=\"https:\/\/docs.microsoft.com\/aspnet\/core\/blazor\/fundamentals\/dependency-injection?view=aspnetcore-3.1#default-services\" target=\"_blank\" rel=\"noopener noreferrer\">HTTP requests are handled by the browser<\/a>, that is why the recommendation is to <a href=\"https:\/\/docs.microsoft.com\/aspnet\/core\/blazor\/call-web-api\" target=\"_blank\" rel=\"noopener noreferrer\">leverage IHttpClientFactory<\/a>. With the below code, we are wiring the SDK client to use the browser for all its data transport operations:<\/p>\n<p>https:\/\/gist.github.com\/ealsur\/d435fe063469fe09235e6d9e9eb81315<\/p>\n<p>&nbsp;<\/p>\n<p>It&#8217;s important to <strong>switch to Gateway mode<\/strong> because Blazor Wasm\u00a0 does not support TCP connections.<\/p>\n<h3>Sharing HttpClients<\/h3>\n<p>What if your application uses the SDK client, but also other HttpClients (maybe you do calls to a REST API), or have other service clients that also use HttpClient, or you are <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/secure-access-to-data#resource-tokens-\" target=\"_blank\" rel=\"noopener noreferrer\">using Resource Tokens to authenticate<\/a> with Cosmos DB?<\/p>\n<p>In those cases, instead of using the IHttpClientFactory, you create new HttpClient instances for each service that needs it, but <strong>reuse a SocketsHttpHandler instance<\/strong> for all of them.<\/p>\n<p>https:\/\/gist.github.com\/ealsur\/87103ca1ccc10b16bde2d44483a937ce<\/p>\n<p>There are two keys here:<\/p>\n<ul>\n<li>Maintain a single SocketsHttpHandler instance and share it.<\/li>\n<li>Create the HttpClient with the <strong>disposeHandler parameter as false<\/strong>.<\/li>\n<\/ul>\n<p>This is also documented as one of the <a href=\"https:\/\/docs.microsoft.com\/aspnet\/core\/fundamentals\/http-requests?view=aspnetcore-3.1#alternatives-to-ihttpclientfactory\" target=\"_blank\" rel=\"noopener noreferrer\">alternatives<\/a> for environments that do not have access to IHttpClientFactory.<\/p>\n<h3>More resources<\/h3>\n<ul>\n<li>Get the <a href=\"https:\/\/www.nuget.org\/packages\/Microsoft.Azure.Cosmos\" target=\"_blank\" rel=\"noopener noreferrer\">latest .NET SDK form Nuget<\/a>.<\/li>\n<li>Check the <a href=\"https:\/\/docs.microsoft.com\/azure\/cosmos-db\/performance-tips-dotnet-sdk-v3-sql\" target=\"_blank\" rel=\"noopener noreferrer\">.NET SDK performance tips<\/a>.<\/li>\n<li>Learn more about <a href=\"https:\/\/docs.microsoft.com\/dotnet\/architecture\/microservices\/implement-resilient-applications\/use-httpclientfactory-to-implement-resilient-http-requests\" target=\"_blank\" rel=\"noopener noreferrer\">IHttpClientFactory in ASP.NET Core applications<\/a>.<\/li>\n<li>View more <a href=\"https:\/\/github.com\/Azure\/azure-cosmos-dotnet-v3\/tree\/master\/Microsoft.Azure.Cosmos.Samples\/Usage\/HttpClientFactory\" target=\"_blank\" rel=\"noopener noreferrer\">samples in GitHub<\/a>.<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In this post, learn about HTTPClientFactory and how you can use it to pool HTTP connections with Azure Cosmos DB clients.<\/p>\n","protected":false},"author":9477,"featured_media":1588,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[14,19],"tags":[499],"class_list":["post-1560","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-core-sql-api","category-tips-and-tricks","tag-azure-cosmos-db"],"acf":[],"blog_post_summary":"<p>In this post, learn about HTTPClientFactory and how you can use it to pool HTTP connections with Azure Cosmos DB clients.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/1560","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/users\/9477"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/comments?post=1560"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/posts\/1560\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media\/1588"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/media?parent=1560"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/categories?post=1560"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/cosmosdb\/wp-json\/wp\/v2\/tags?post=1560"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}