我正在使用类型化客户端IHttpClientFactory。像这样:
// Startup.cs
services.AddHttpClient<MyHttpClient>()
// MyHttpClient.cs
public class MyHttpClient
{
public MyHttpClient(HttpClient client)
{
Client = client;
}
public HttpClient Client { get; }
}
// MyService.cs
public class MyService {
public MyService(MyHttpClient httpClient) {}
public async Task SendRequestAsync(string uri, string accessToken) {
_httpClient.Client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
await _httpClient.Client.GetAsync(uri);
}
}
Run Code Online (Sandbox Code Playgroud)
我不确定这是如何运作的。请求标头是仅针对此请求设置,还是针对使用 . 的此实例发出的每个后续请求设置httpClient。如何为每个请求设置标头?
刚开始使用 HttpFactory,并且非常困惑它的 DI 是如何工作的,例如这条线的工作方式
services.AddHttpClient<IMyClient, MyClient>()
.AddHttpMessageHandler(s => new UserAgentDelegatingHandler());
Run Code Online (Sandbox Code Playgroud)
这不
services.AddHttpClient<IMyClient, MyClient>()
.AddHttpMessageHandler<UserAgentDelegatingHandler>();
Run Code Online (Sandbox Code Playgroud)
返回
“消息:System.InvalidOperationException:没有注册‘UserAgentDelegatingHandler’类型的服务。”
这里的情况相同,以下代码工作正常
services.AddHttpContextAccessor();
services.AddHttpClient<IMyClient, MyClient>()
.AddHttpMessageHandler(s => new CookieDelegateHandler(s.GetRequiredService<IHttpContextAccessor>()));
Run Code Online (Sandbox Code Playgroud)
但这并没有
services.AddHttpContextAccessor();
services.AddHttpClient<IMyClient, MyClient>()
.AddHttpMessageHandler<CookieDelegateHandler>();
Run Code Online (Sandbox Code Playgroud)
我从这些示例中阅读了很多 HttpClientFactory 用法示例,以及我的 DelegateHandlers。
我做错了什么?
我使用 IHttpClientFactory 发送请求并接收从我的 Web API 到使用 Net Core 2.2 的外部 API 的 HTTP 响应。
用于向 API 发送请求的访问令牌和刷新令牌已存储在 appsettings.json 中。当请求返回 403 或 401 错误时,我会动态获取一个新令牌并将其添加到请求的标头中。
但是如何使用新的访问和刷新令牌更新 appsettings.json 以便将其用于后续请求。
是否有比 appsettings.json 更好的方法来存储访问和刷新令牌?
我有一个带有简单消费后台服务的控制台程序,它需要从使用 HttpClientFactory 的作用域服务调用函数来调用外部 API 并将结果返回给消费后台服务。
在网上查看了几个示例后,我想要非常简单,以消除代码中所有可能的复杂性。
public class Program
{
public static async Task Main(string[] args)
{
var host = new HostBuilder()
.ConfigureLogging((hostContext, config) =>
{
config.AddConsole();
})
.ConfigureAppConfiguration((hostContext, config) =>
{
config.AddJsonFile("appsettings.json", optional: true);
config.AddJsonFile($"appsettings.{Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production"}.json", optional: true);
config.AddCommandLine(args);
})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<ConsumeMessageService>();
services.AddScoped<IScopedArcGisServices, ScopedArcGisServices>();
})
.UseConsoleLifetime()
.Build();
using (host)
{
// Start the host
await host.StartAsync();
// Wait for the host to shutdown
await host.WaitForShutdownAsync();
}
}
}
Run Code Online (Sandbox Code Playgroud)
public class ConsumeMessageService : IHostedService
{
private …Run Code Online (Sandbox Code Playgroud) c# dependency-injection httpclientfactory asp.net-core-hosted-services
在 VS 2019 中,我尝试HttpClient在 Blazor WebAssemply 应用程序中测试使用。创建新项目时,我选择了该.Net Core 3.1选项。在Program.cs中,HttpClient服务注册如下:
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
Run Code Online (Sandbox Code Playgroud)
在“框架”部分下,system.net.http列出了。
@inject IHttpClientFactory http我们遇到了无法添加新 Razor 组件的问题。错误消息是:
错误 CS0246 找不到类型或命名空间名称“IHttpClientFactory”(您是否缺少 using 指令或程序集引用?)
Microsoft 站点的在线文档显示了IHttpClientFactory在System.Net.Http包中定义的。我遇到的错误的根本原因是什么以及如何修复它?
我需要进行一系列 HTTP 调用以从第 3 方保管库获取数据库凭据,因为我需要运行此代码Program.cs,或者最晚Startup.cs在添加 DBContext 之前,我需要能够在不使用 DBContext 的情况下进行这些调用使用IHttpClientFactory,因为这需要依赖注入已经初始化。
以下代码在运行时调用时工作正常,但在步骤期间不起作用ConfigureAppConfiguration。
HttpClient client = _clientFactory.CreateClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, $"{_configuration["CredentialsVault:vaultUrl"]}Auth/SignAppIn");
request.Headers.Add("Authorization", $"PS-Auth key={_apiKey}; runas={_runAsUser};");
var response = await client.SendAsync(request);
Run Code Online (Sandbox Code Playgroud)
有没有一种方法可以在不依赖依赖注入的情况下进行 HTTP 调用,或者延迟AddDbContext到依赖注入设置之后?
我尝试创建一个 HttpClient 实例,如下所示:
HttpClient client = new HttpClient();
Run Code Online (Sandbox Code Playgroud)
然而,这似乎不起作用,根据这个问题,它不应该像这样实例化。
我正在设计一个.net核心Web API,它使用了我无法控制的外部API。我在堆栈溢出中找到了一些极好的答案,这些问题使我可以在使用semaphoreslim的同一线程中限制对此外部API的请求。我想知道如何最好地将这种限制扩展到整个应用程序,而不仅仅是限制特定任务列表。我一直在学习HttpMessageHandlers,这似乎是拦截所有传出消息并应用限制的一种可能方法。但是我担心线程安全性和锁定问题,我可能不了解。我包括了当前的限制代码,希望对理解我正在尝试做的事情有所帮助,但是要跨越多个线程,并且不断添加任务而不是预先定义的任务列表。
private static async Task<List<iMISPagedResultResponse>> GetAsyncThrottled(List<int> pages, int throttle, IiMISClient client, string url, int limit)
{
var rtn = new List<PagedResultResponse>();
var allTasks = new List<Task>();
var throttler = new SemaphoreSlim(initialCount: throttle);
foreach (var page in pages)
{
await throttler.WaitAsync();
allTasks.Add(
Task.Run(async () =>
{
try
{
var result = await GetPagedResult(client, url, page);
return result;
}
finally
{
throttler.Release();
}
}));
}
await Task.WhenAll(allTasks);
foreach (var task in allTasks)
{
var result = ((Task<PagedResultResponse>)task).Result;
rtn.Add(result);
}
return rtn; …Run Code Online (Sandbox Code Playgroud) 我有许多 CRUD API,它们通过 HTTP 调用 (.NET 5) 相互通信。
为了避免打开太多的 tcp 连接,我在所有这些服务中通过 DI使用HttpClientFactory 。这效果很好,我没有遇到太多通过 HTTP 打开的连接。
但我的 Azure 应用服务仍然抱怨 SNAT 连接过多:
我猜原因是Azure服务总线。我的 API 的每次调用都会将事件写入总线。
为此,我在每次调用时创建一个新实例:
await using (ServiceBusClient client = new ServiceBusClient(_serviceBusConnectionString))
{
var messageObject = new { message.Name, message.Body };
var messageJson = JsonConvert.SerializeObject(messageObject);
ServiceBusSender sender = client.CreateSender(_topicName);
await sender.SendMessageAsync(new ServiceBusMessage(messageJson));
}
Run Code Online (Sandbox Code Playgroud)
许多开发人员都像这样使用 HttpClient(这是一个坏主意,请阅读上面的文章中的原因)。HttpClient 的解决方案是 .NET 为此目的提供的 AddHttpClient 方法。
但是 Azure 服务总线呢?没有什么像 AzureServiceBusFactory 之类的东西,将 AzureServiceBus 添加为单例并不是一个好主意,因为每次调用的配置都应该不同。
如何确保连接池也重新用于 Azure 服务总线连接?我错过了什么最佳实践吗?或者您认为连接问题还有其他原因吗?
编辑:
接受的答案是正确的。这工作正常,我的错误消失了。只需使用以下命令添加服务总线客户端:
services.AddAzureClients(cfg =>
{
cfg.AddServiceBusClient("your-connection-string");
});
Run Code Online (Sandbox Code Playgroud)
之后,您就可以在您的所有服务中轻松通过 DI …
c# ×6
asp.net-core ×4
.net-5 ×1
.net-core ×1
asp.net-core-hosted-services ×1
blazor ×1
semaphore ×1
token ×1