HttpClient使用-秋风
起因
在项目中需要访问Http请求的时候,通常都是使用WebRequest,主要是老项目(你懂得).如果不是老项目,应该使用HttpClient,但在.Net Core 2.1之后,官方可推荐使用使用HttpClientFactory.1. HttpClient的使用
public static async void UseHttp()
{
HttpClient httpClient = new HttpClient(); //静态实例,主要是为了复用Tcp连接,用在项目中要进行封装
httpClient.BaseAddress = new Uri("http://localhost:5000"); //要访问的基地址,ip加端口
string result = await httpClient.GetStringAsync("/Home/GetHtmlData");
Console.WriteLine(result);
}
2.在Asp.Net Core使用HttpClientFactory
在Startup文件的ConfigureServices函数,注册HttpClient中间件//在容器中注册HttpClient中间件
services.AddHttpClient("baidu", client =>
{
client.BaseAddress = new Uri("http://localhost:5000");
//还可以请求定制化
});
/// <summary>
///
/// </summary>
/// <param name="logger">日志</param>
/// <param name="peopleService">注入IPeopleService的实现</param>
/// <param name="service">注入IService的实现</param>
/// <param name="cache">缓存</param>
/// <param name="httpClientFactory">容器在实例化HomeController的时候,会先实现IHttpClientFactory的实现DefaultHttpClientFactory(AddHttpClient在容器中注册)</param>
public HomeController(ILogger<HomeController> logger,
IPeopleService peopleService,
AOP.IService service,
IMemoryCache cache,
IHttpClientFactory httpClientFactory)
{
Console.WriteLine("有参数构造 HomeController");
this._logger = logger;
this._peopleService = peopleService;
this._service = service;
this._cache = cache;
this._httpClientFactory = httpClientFactory;
}
/// <summary>
/// 使用HttpClient请求
/// </summary>
/// <returns></returns>
public async Task<string> GetHtmlData()
{
//通过DefaultHttpClientFactory的CreateClient获取HttpClient实例
var client = _httpClientFactory.CreateClient("baidu");
return await client.GetStringAsync("/");
}
在Asp.Net Core的HttpClient中间件源码
/// <summary>
/// Adds the <see cref="IHttpClientFactory"/> and related services to the <see cref="IServiceCollection"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <returns>The <see cref="IServiceCollection"/>.</returns>
public static IServiceCollection AddHttpClient(this IServiceCollection services)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
services.AddLogging();
services.AddOptions();
//
// Core abstractions
//
services.TryAddTransient<HttpMessageHandlerBuilder, DefaultHttpMessageHandlerBuilder>();
services.TryAddSingleton<DefaultHttpClientFactory>();
services.TryAddSingleton<IHttpClientFactory>(serviceProvider => serviceProvider.GetRequiredService<DefaultHttpClientFactory>());
services.TryAddSingleton<IHttpMessageHandlerFactory>(serviceProvider => serviceProvider.GetRequiredService<DefaultHttpClientFactory>());
//
// Typed Clients
//
services.TryAdd(ServiceDescriptor.Transient(typeof(ITypedHttpClientFactory<>), typeof(DefaultTypedHttpClientFactory<>)));
services.TryAdd(ServiceDescriptor.Singleton(typeof(DefaultTypedHttpClientFactory<>.Cache), typeof(DefaultTypedHttpClientFactory<>.Cache)));
//
// Misc infrastructure
//
services.TryAddEnumerable(ServiceDescriptor.Singleton<IHttpMessageHandlerBuilderFilter, LoggingHttpMessageHandlerBuilderFilter>());
// This is used to track state and report errors **DURING** service registration. This has to be an instance
// because we access it by reaching into the service collection.
services.TryAddSingleton(new HttpClientMappingRegistry());
// Register default client as HttpClient
services.TryAddTransient(s =>
{
return s.GetRequiredService<IHttpClientFactory>().CreateClient(string.Empty);
});
return services;
}
/// <summary>
/// Adds the <see cref="IHttpClientFactory"/> and related services to the <see cref="IServiceCollection"/> and configures
/// a named <see cref="HttpClient"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <param name="name">The logical name of the <see cref="HttpClient"/> to configure.</param>
/// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns>
/// <remarks>
/// <para>
/// <see cref="HttpClient"/> instances that apply the provided configuration can be retrieved using
/// <see cref="IHttpClientFactory.CreateClient(string)"/> and providing the matching name.
/// </para>
/// <para>
/// Use <see cref="Options.Options.DefaultName"/> as the name to configure the default client.
/// </para>
/// </remarks>
public static IHttpClientBuilder AddHttpClient(this IServiceCollection services, string name)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
AddHttpClient(services);
return new DefaultHttpClientBuilder(services, name);
}
/// <summary>
/// Adds the <see cref="IHttpClientFactory"/> and related services to the <see cref="IServiceCollection"/> and configures
/// a named <see cref="HttpClient"/>.
/// </summary>
/// <param name="services">The <see cref="IServiceCollection"/>.</param>
/// <param name="name">The logical name of the <see cref="HttpClient"/> to configure.</param>
/// <param name="configureClient">A delegate that is used to configure an <see cref="HttpClient"/>.</param>
/// <returns>An <see cref="IHttpClientBuilder"/> that can be used to configure the client.</returns>
/// <remarks>
/// <para>
/// <see cref="HttpClient"/> instances that apply the provided configuration can be retrieved using
/// <see cref="IHttpClientFactory.CreateClient(string)"/> and providing the matching name.
/// </para>
/// <para>
/// Use <see cref="Options.Options.DefaultName"/> as the name to configure the default client.
/// </para>
/// </remarks>
public static IHttpClientBuilder AddHttpClient(this IServiceCollection services, string name, Action<HttpClient> configureClient)
{
if (services == null)
{
throw new ArgumentNullException(nameof(services));
}
if (name == null)
{
throw new ArgumentNullException(nameof(name));
}
if (configureClient == null)
{
throw new ArgumentNullException(nameof(configureClient));
}
AddHttpClient(services);
var builder = new DefaultHttpClientBuilder(services, name);
builder.ConfigureHttpClient(configureClient);
return builder;
}
在.Net 6加入Minimal API
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
//在.Net 6中,使用Minimal api
builder.Services.AddHttpClient("test", client =>
{
client.BaseAddress = new Uri("http://localhost:5000");
});
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.MapRazorPages();
//在这里注入IHttpClientFactory
app.MapGet("/", async (IHttpClientFactory httpClientFactory) =>
{
var client = httpClientFactory.CreateClient("test");
return await client.GetStringAsync("/");
});
app.Run();
秋风
2020-09-29