使用依赖注入配置 HttpClient,其中一个客户端需要来自另一个客户端的信息
Configuring HttpClient using dependency injection where one client needs information from another
我有一个 .NET Core 3.0 控制台应用程序(尽管我打算稍后将其更改为 Blazor 应用程序)。
在我的程序 class 的 public static void Main
方法中,我正在使用 Microsoft here.
描述的模式配置依赖注入
特别是,我想使用 here 描述的 "named clients" 模式注册少数 HttpClient
个实例。
一切都很好,除了这个问题:我的第二个和第三个 HttpClient
实例应该有一个 DefaultRequestHeader
传递会话 ID。但是在我执行 API 命令以使用第一个 HttpClient
实例登录到远程服务器之前,我不会知道会话 ID 的值。我该怎么办?
到目前为止我的代码如下。
我能否以某种方式获得对第一个 HttpClient
实例的引用并从该代码块内部调用我的 Login
方法?或者我可以稍后从不同的代码块调用 Login
方法,然后在实例化很久之后将适当的 DefaultRequestHeader
添加到其他 HttpClient
实例吗?
public class Program
{
public static void Main()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddUserSecrets<Program>()
.AddEnvironmentVariables(); ;
IConfigurationRoot configuration = builder.Build();
var settings = new ApplicationOptions();
configuration.GetSection("AppSettings").Bind(settings);
var services = new ServiceCollection();
// This is the client I'll use to log in and get a session token
services.AddHttpClient("Authentication", c =>
{
c.BaseAddress = new Uri(settings.AuthenticationApi);
c.DefaultRequestHeaders.Accept.Clear();
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
c.DefaultRequestHeaders.Add("X-Application", settings.AppKey);
c.DefaultRequestHeaders.Add("User-Agent", "My API Client v0.0.1");
}).ConfigurePrimaryHttpMessageHandler(() =>
{
return GetMessageHandlerWithSecurityCertificate(settings);
});
// and this is the next of several clients where I'll need to send the session token with my requests
services.AddHttpClient("AnotherApi", c =>
{
c.BaseAddress = new Uri(settings.AnotherApi);
c.DefaultRequestHeaders.Accept.Clear();
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
c.DefaultRequestHeaders.Add("X-Application", settings.AppKey);
c.DefaultRequestHeaders.Add("User-Agent", "My API Client v0.0.1");
//c.DefaultRequestHeaders.Add("ssoid", sessionToken);
// What should I do here? I want to add a sessionToken string but I can only get the token's value by using the other HttpClient (above) to log in!
});
// Removed one more HttpClient for brevity
}
private static HttpMessageHandler GetMessageHandlerWithSecurityCertificate(ApplicationOptions settings)
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(GetSecurityCertificate(settings.SslCertificateFilename, settings.SslCertificatePassword));
return handler;
}
private static X509Certificate2 GetSecurityCertificate(string certFilename, string certPassword)
{
return new X509Certificate2(certFilename, certPassword);
}
}
您能否不直接使用 IHttpClientFactory 并在需要时使用您的凭据生成 HttpClient?换句话说,与其尝试注册所有单独的 HttpClient,不如正常注册 IHttpClientFactory。将其注入到需要 HttpClient 的 class 中,然后使用您的凭据在那里创建它?那就是我会做的。毕竟,IHttpClientFactory 只是一个包装器 class,它使用工厂模式生成 HttpClient。
另外:在一段时间内,您可以使用扩展方法为您的 HttpClient 配置预设值,以在任何地方保存重复代码以获得一致的内容。
我有一个 .NET Core 3.0 控制台应用程序(尽管我打算稍后将其更改为 Blazor 应用程序)。
在我的程序 class 的 public static void Main
方法中,我正在使用 Microsoft here.
特别是,我想使用 here 描述的 "named clients" 模式注册少数 HttpClient
个实例。
一切都很好,除了这个问题:我的第二个和第三个 HttpClient
实例应该有一个 DefaultRequestHeader
传递会话 ID。但是在我执行 API 命令以使用第一个 HttpClient
实例登录到远程服务器之前,我不会知道会话 ID 的值。我该怎么办?
到目前为止我的代码如下。
我能否以某种方式获得对第一个 HttpClient
实例的引用并从该代码块内部调用我的 Login
方法?或者我可以稍后从不同的代码块调用 Login
方法,然后在实例化很久之后将适当的 DefaultRequestHeader
添加到其他 HttpClient
实例吗?
public class Program
{
public static void Main()
{
var builder = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
.AddUserSecrets<Program>()
.AddEnvironmentVariables(); ;
IConfigurationRoot configuration = builder.Build();
var settings = new ApplicationOptions();
configuration.GetSection("AppSettings").Bind(settings);
var services = new ServiceCollection();
// This is the client I'll use to log in and get a session token
services.AddHttpClient("Authentication", c =>
{
c.BaseAddress = new Uri(settings.AuthenticationApi);
c.DefaultRequestHeaders.Accept.Clear();
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
c.DefaultRequestHeaders.Add("X-Application", settings.AppKey);
c.DefaultRequestHeaders.Add("User-Agent", "My API Client v0.0.1");
}).ConfigurePrimaryHttpMessageHandler(() =>
{
return GetMessageHandlerWithSecurityCertificate(settings);
});
// and this is the next of several clients where I'll need to send the session token with my requests
services.AddHttpClient("AnotherApi", c =>
{
c.BaseAddress = new Uri(settings.AnotherApi);
c.DefaultRequestHeaders.Accept.Clear();
c.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
c.DefaultRequestHeaders.Add("X-Application", settings.AppKey);
c.DefaultRequestHeaders.Add("User-Agent", "My API Client v0.0.1");
//c.DefaultRequestHeaders.Add("ssoid", sessionToken);
// What should I do here? I want to add a sessionToken string but I can only get the token's value by using the other HttpClient (above) to log in!
});
// Removed one more HttpClient for brevity
}
private static HttpMessageHandler GetMessageHandlerWithSecurityCertificate(ApplicationOptions settings)
{
var handler = new HttpClientHandler();
handler.ClientCertificates.Add(GetSecurityCertificate(settings.SslCertificateFilename, settings.SslCertificatePassword));
return handler;
}
private static X509Certificate2 GetSecurityCertificate(string certFilename, string certPassword)
{
return new X509Certificate2(certFilename, certPassword);
}
}
您能否不直接使用 IHttpClientFactory 并在需要时使用您的凭据生成 HttpClient?换句话说,与其尝试注册所有单独的 HttpClient,不如正常注册 IHttpClientFactory。将其注入到需要 HttpClient 的 class 中,然后使用您的凭据在那里创建它?那就是我会做的。毕竟,IHttpClientFactory 只是一个包装器 class,它使用工厂模式生成 HttpClient。
另外:在一段时间内,您可以使用扩展方法为您的 HttpClient 配置预设值,以在任何地方保存重复代码以获得一致的内容。