Author : HASSAN MD TAREQ | Updated : 2020/10/21
Introduction
HttpClient
: Provides a base class for sending HTTP requests and receiving HTTP responses from a resource identified by a URI.IHttpClientFactory
: A factory abstraction for a component that can create HttpClient instances with custom configuration for a given logical name- Links:
- https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests
- https://docs.microsoft.com/en-us/dotnet/api/system.net.http.httpclient
- https://stackoverflow.com/a/53715282/4802664
- https://josef.codes/you-are-probably-still-using-httpclient-wrong-and-it-is-destabilizing-your-software/
- https://medium.com/cheranga/calling-web-apis-using-typed-httpclients-net-core-20d3d5ce980
- https://www.stevejgordon.co.uk/introduction-to-httpclientfactory-aspnetcore
- Http client libraries:
- Flurl.Http
- Refit
- RestSharp
Setup for dependency injection
- Set BaseUri in
appsettings.json
- During development, use dev BaseUri (i.e.
https://localhost:44321/api/
) - For production, set BaseUri in Azure App Service or set by Azure DevOps pipeline (variable translation)
- During development, use dev BaseUri (i.e.
- Configure HTTP Client in
Startup.cs
- Scope: Singleton
- Get ServicePoint and set desired properties (i.e.
servicePoint.ConnectionLeaseTimeout = 6000
)
appsettings.json
{
"APIHost": "https://localhost:44321/api/",
}
Constants.cs
public static class Constants
{
public static readonly string KEY_API_BASE_URI = "APIHost";
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
// ... ... ...
// Configure HTTP Client
var apiAddress = Configuration[Constants.KEY_API_BASE_URI];
Uri apiBaseUri = new Uri(apiAddress);
HttpClient apiClient = new HttpClient();
apiClient.BaseAddress = apiBaseUri;
var servicePoint = ServicePointManager.FindServicePoint(apiBaseUri);
servicePoint.ConnectionLeaseTimeout = 60000;
services.AddSingleton<HttpClient>(apiClient);
}
Usage in controller by dependency injection
ProductController .cs
using Newtonsoft.Json.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace Foo.Controllers
{
public class ProductController : Controller
{
HttpClient client;
public ProductController(HttpClient apiClient)
{
client = apiClient;
}
public async Task<IActionResult> Index()
{
var response = await client.GetStringAsync("product");
var products = JArray.Parse(response);
return View(products);
}
public async Task<IActionResult> Detail(int id)
{
var response = await client.GetStringAsync($"product/{id}" );
var product = JsonConvert.DeserializeObject<Models.Product>(response);
return View(product);
}
}
}
public class Product
{
public int ID { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string ImageTitle { get; set; }
public string Image { get; set; }
}
Json Serialization
- New namespace for netcore:
System.Text.Json
(aspnet core 3.0+) - https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-how-to
- https://devblogs.microsoft.com/dotnet/try-the-new-system-text-json-apis/
To serialize
using System.Text.Json;
using System.Text.Json.Serialization;
var jsonStr = JsonSerializer.Serialize(MyObject)
To deserialize
var weatherForecast = JsonSerializer.Deserialize<MyObject>(jsonStr);
Using vanilla IHttpClientFactory and HttpClient
Typed client
RepoService.cs
public class RepoService
{
private readonly HttpClient _httpClient;
public RepoService(HttpClient client)
{
_httpClient = client;
}
public async Task<IEnumerable<string>> GetRepos()
{
var response = await _httpClient.GetAsync("aspnet/repos");
response.EnsureSuccessStatusCode();
using var responseStream = await response.Content.ReadAsStreamAsync(); // inline 'using' => C# 8.0+
return await JsonSerializer.DeserializeAsync<IEnumerable<string>>(responseStream);
}
}
Startup.ConfigureServices(...)
services.AddHttpClient<RepoService>(repoClient =>
{
repoClient.BaseAddress = new Uri("https://api.github.com/");
repoClient.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
repoClient.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
});
Usage
public class TypedClientModel : PageModel
{
private readonly GitHubService _gitHubService;
public TypedClientModel(GitHubService gitHubService)
{
_gitHubService = gitHubService;
}
public async Task OnGet()
{
try
{
var issues = await _gitHubService.GetAspNetDocsIssues();
}
catch(HttpRequestException)
{
// ... ... ...
}
}
}
See:
- Samples : https://github.com/dotnet/AspNetCore.Docs/tree/master/aspnetcore/fundamentals/http-requests/samples
- Named-clients : https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests#named-clients
- Make requests : https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests#make-post-put-and-delete-requests
Querying CosmosDB
- Select Storage account > Select target CosmosDB
- Get keys
- See: Querying Azure Cosmos DB
Flurl
- PMC:
Install-Package Flurl.Http
- Links
Refit
- PMC:
Install-Package refit
- Links:
- https://github.com/reactiveui/refit
- IHttpClientFactory with Refit:
- https://docs.microsoft.com/en-us/aspnet/core/fundamentals/http-requests#generated-clients
Install-Package Refit.HttpClientFactory
- https://www.hanselman.com/blog/UsingASPNETCore21sHttpClientFactoryWithRefitsRESTLibrary.aspx
Generating http client with NSwag
- CLI:
dotnet-nswag.dll
is a command line tool for .Net core- https://github.com/RicoSuter/NSwag/wiki/CommandLine
- CodeGeneration nuget package:
- Generates client inside project using
dotnet-nswag.dll
- PMC:
Install-Package NSwag.AspNetCore
(https://www.nuget.org/packages/NSwag.AspNetCore/)Install-Package NSwag.CodeGeneration.CSharp
(https://www.nuget.org/packages/NSwag.CodeGeneration.CSharp/)
- You need to write C# code to generate client(C# API exposed by
NSwag.CodeGeneration.CSharp
) - https://github.com/RicoSuter/NSwag/wiki/CSharpClientGenerator
- Generates client inside project using
- NSwagStudio:
- https://github.com/RicoSuter/NSwag/wiki/NSwagStudio
- Download latest NSwagStudio MSI installer (Windows Desktop application)
- https://blog.rsuter.com/nswag-tutorial-integrate-the-nswag-toolchain-into-your-asp-net-web-api-project/
- Use HTTP Client Factory with NSwag Generated Classes :
- Visual Studio extension:
- NSwag.MSBuild:
- Allows to run the NSwag command line tool in an MSBuild target (
.csproj
file) - NSwag.MSBuild NuGet package generates code for our API clients before the project is build, this way we can generate our code and compile it everytime you build your project
- https://github.com/RicoSuter/NSwag/wiki/NSwag.MSBuild
- https://blog.sanderaernouts.com/autogenerate-csharp-api-client-with-nswag
- https://stu.dev/generating-typed-client-for-httpclientfactory-with-nswag/
- Allows to run the NSwag command line tool in an MSBuild target (
- https://github.com/RicoSuter/NSwag/wiki/NSwag-Configuration-Document