@ -32,7 +32,7 @@
},
{
"cell_type": "code",
"execution_count": 67 ,
"execution_count": 5 ,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
@ -48,7 +48,7 @@
{
"data": {
"text/html": [
"<div><div></div><div></div><div><strong>Installed Packages</strong><ul><li><span>Microsoft.Extensions.DependencyInjection, 8.0.0</span></li><li><span>Microsoft.Extensions.Http, 8.0.0</span></li><li><span>Microsoft.Extensions.Http.Polly, 8.0.7</span></li><li><span>Polly, 8.4.1</span></li><li><span>System.Net.Http.Json, 8.0.0</span></li></ul></div></div>"
"<div><div></div><div></div><div><strong>Installed Packages</strong><ul><li><span>Microsoft.Extensions.DependencyInjection, 8.0.0</span></li><li><span>Microsoft.Extensions.Http, 8.0.0</span></li><li><span>Microsoft.Extensions.Http.Polly, 8.0.7</span></li><li><span>Polly, 8.4.1</span></li><li><span>Refit, 7.1.2</span></li><li><span>Refit.HttpClientFactory, 7.1.2</span></li><li><span> System.Net.Http.Json, 8.0.0</span></li></ul></div></div>"
]
},
"metadata": {},
@ -58,23 +58,9 @@
"name": "stdout",
"output_type": "stream",
"text": [
"启动WebApi项目\r\n"
]
},
{
"data": {
"text/plain": [
"e:\\王高峰\\我的项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"程序[e:\\王高峰\\我的项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!\r\n"
"配置文件根目录: e:\\王高峰\\我的项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n",
"启动WebApi项目\n",
"程序[e:\\王高峰\\我的项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!\n"
]
}
],
@ -85,6 +71,8 @@
"#r \"nuget:Microsoft.Extensions.DependencyInjection\"\n",
"#r \"nuget:Polly\"\n",
"#r \"nuget:Microsoft.Extensions.Http.Polly\"\n",
"#r \"nuget:Refit\" \n",
"#r \"nuget:Refit.HttpClientFactory\"\n",
"#r \"./Publish/HttpClientStudy.Core/HttpClientStudy.Core.dll\"\n",
"\n",
"global using System;\n",
@ -121,15 +109,21 @@
"global using Polly.Registry;\n",
"global using Polly.Telemetry;\n",
"\n",
"global using Refit;\n",
"//global using Refit.HttpClientFactory;\n",
"\n",
"global using HttpClientStudy.Config;\n",
"global using HttpClientStudy.Core;\n",
"global using HttpClientStudy.Core.Utilities;\n",
"\n",
"//启动已发布的WebApi项目 \n",
"Console.WriteLine(\"启动WebApi项目\") ;\n",
"//全局变量 \n",
"var webApiBaseUrl = WebApiConfigManager.GetWebApiConfig().BaseUrl ;\n",
"var workDir = Environment.CurrentDirectory;\n",
"var fullPath = System.IO.Path.GetFullPath(\"./Publish/HttpClientStudy.WebApp/HttpClientStudy.WebApp.exe\", workDir);\n",
"fullPath.Display();\n",
"//fullPath.Display();\n",
"\n",
"//启动已发布的WebApi项目\n",
"Console.WriteLine(\"启动WebApi项目\");\n",
"var startMessage = AppUtility.RunWebApiExeFile(fullPath);\n",
"Console.WriteLine(startMessage);\n"
]
@ -690,23 +684,19 @@
},
{
"cell_type": "code",
"execution_count": 36 ,
"execution_count": null ,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"9193\n",
"9193\n",
"18\n"
]
}
],
"outputs": [],
"source": [
"/*\n",
" 注意:\n",
@ -770,22 +760,19 @@
},
{
"cell_type": "code",
"execution_count": 55 ,
"execution_count": null ,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"A: 9508\n",
"A: 18\n"
]
}
],
"outputs": [],
"source": [
"// IoC 多个HttpClient服务类\n",
"\n",
@ -870,49 +857,209 @@
},
{
"cell_type": "code",
"execution_count": 68 ,
"execution_count": null ,
"metadata": {
"dotnet_interactive": {
"language": "csharp"
},
"polyglot_notebook": {
"kernelName": "csharp"
},
"vscode": {
"languageId": "polyglot-notebook"
}
},
"outputs": [
{
"ename": "Error",
"evalue": "System.InvalidOperationException: An invalid request URI was provided. Either the request URI must be an absolute URI or BaseAddress must be set.\r\n at System.Net.Http.HttpClient.PrepareRequestMessage(HttpRequestMessage request)\r\n at System.Net.Http.HttpClient.GetAsync(String requestUri)\r\n at Submission#69.<<Initialize>>d__0.MoveNext()\r\n--- End of stack trace from previous location ---\r\n at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)",
"output_type": "error",
"traceback": [
"System.InvalidOperationException: An invalid request URI was provided. Either the request URI must be an absolute URI or BaseAddress must be set.\r\n",
" at System.Net.Http.HttpClient.PrepareRequestMessage(HttpRequestMessage request)\r\n",
" at System.Net.Http.HttpClient.GetAsync(String requestUri)\r\n",
" at Submission#69.<<Initialize>>d__0.MoveNext()\r\n",
"--- End of stack trace from previous location ---\r\n",
" at Microsoft.CodeAnalysis.Scripting.ScriptExecutionState.RunSubmissionsAsync[TResult](ImmutableArray`1 precedingExecutors, Func`2 currentExecutor, StrongBox`1 exceptionHolderOpt, Func`2 catchExceptionOpt, CancellationToken cancellationToken)"
]
}
],
"outputs": [],
"source": [
"//基础使用 \n",
"//所有HttpClient配置\n",
"{\n",
" var services = new ServiceCollection();\n",
" services.AddHttpClient<HttpClient>((provider, client) => \n",
" //添加一个委托, 用于配置所有HttpClient实例。只执行一次。\n",
" services.ConfigureHttpClientDefaults(builder => \n",
" {\n",
" client.BaseAddress = new Uri(\"https://www.baidu.com\");\n",
" //builder.UseSocketsHttpHandler();\n",
" //builder.SetHandlerLifetime(TimeSpan.FromMinutes(5));\n",
" \n",
" builder.ConfigureHttpClient(hc =>\n",
" {\n",
" hc.BaseAddress = new Uri(webApiBaseUrl);\n",
" });\n",
" });\n",
"\n",
" var factory = services.BuildServiceProvider().GetRequiredService<IHttpClientFactory>();\n",
"\n",
" var client = factory.CreateClient();\n",
" var response = await client.GetAsync(\"/api/hello/ping\");\n",
" var data = await response.Content.ReadAsStringAsync();\n",
" Console.WriteLine(data);\n",
"}\n",
"\n",
"/*\n",
" 默认 HttpClient\n",
" 1、配置默认HttpClient时, AddHttpClient(Action)的Action不会被执行, ConfigureHttpClient()也不执行。原因暂时不明\n",
" 2、想配置默认HttpClient, 可以使用ConfigureHttpClientDefaults方法, 但此方法针对所有HttpClient实例(包括命名HttpClient)\n",
"*/\n",
"{\n",
" var services = new ServiceCollection();\n",
"\n",
" //默认HttpClient\n",
" services.AddHttpClient<HttpClient>();\n",
"\n",
" //这种形式,不生效\n",
" // services.AddHttpClient<HttpClient>((provider, client) => \n",
" // {\n",
" // client.BaseAddress = new Uri(webApiBaseUrl);\n",
" // });\n",
"\n",
" //这种形式, ConfigureHttpClient 也不生效\n",
" // services.AddHttpClient<HttpClient>()\n",
" // .ConfigureHttpClient(config=>\n",
" // {\n",
" // config.BaseAddress = new Uri(webApiBaseUrl);\n",
" // });\n",
"\n",
" var provider = services.BuildServiceProvider();\n",
"\n",
" var factory = provider.GetRequiredService<IHttpClientFactory>();\n",
"\n",
" var sum = factory.CreateClient().GetAsync(\"/\").Result.Content.ReadAsStringAsync().Result.Length;\n",
" var response = await factory.CreateClient().GetAsync(webApiBaseUrl+\"/api/hello/index\");\n",
" var content = await response.Content.ReadAsStringAsync();\n",
" \n",
" Console.WriteLine(sum);\n",
" Console.WriteLine(content );\n",
"}\n",
"\n",
"//\n",
"//命名 HttpClient \n",
"{\n",
" var clientA =\"httpClientA\";\n",
" var clientB =\"httpClientB\";\n",
"\n",
"}"
" var services = new ServiceCollection();\n",
" services.AddHttpClient<HttpClient>(clientA, (provider, client) => \n",
" {\n",
" client.BaseAddress = new Uri(webApiBaseUrl);\n",
" });\n",
" services.AddHttpClient<HttpClient>(clientB, (provider, client) => \n",
" {\n",
" client.DefaultVersionPolicy = HttpVersionPolicy.RequestVersionOrHigher;\n",
" client.BaseAddress = new Uri(webApiBaseUrl);\n",
" })\n",
" .ConfigureHttpClient(client=>\n",
" {\n",
" client.Timeout = TimeSpan.FromSeconds(1);\n",
" client.DefaultRequestVersion = new Version(1, 1);\n",
" });\n",
"\n",
" var factory = services.BuildServiceProvider().GetRequiredService<IHttpClientFactory>();\n",
"\n",
" var responseA = await factory.CreateClient(clientA).GetAsync(\"/api/hello/ping\");\n",
" var contentA = await responseA.Content.ReadAsStringAsync();\n",
" Console.WriteLine(contentA);\n",
"\n",
" var responseB = await factory.CreateClient(clientB).PostAsync(\"/api/hello/post\",null);\n",
" var contentB = await responseB.Content.ReadAsStringAsync();\n",
" Console.WriteLine(contentB);\n",
"}\n",
"\n",
"// 类型化客户端 HttpClient\n",
"public class HttpClientServiceA\n",
"{\n",
" public HttpClient Client { get; }\n",
" public HttpClientServiceA(HttpClient client)\n",
" {\n",
" Client = client;\n",
" Console.WriteLine(\"HttpClientServiceA => 构造函数执行一次\");\n",
" }\n",
"\n",
" public async Task<string> GetIndexAsync()\n",
" {\n",
" var response = await Client.GetAsync(\"/api/hello/index\");\n",
" var content = await response.Content.ReadAsStringAsync();\n",
" return content;\n",
" }\n",
"}\n",
"\n",
"public class HttpClientServiceB\n",
"{\n",
" public HttpClient Client { get; }\n",
" public HttpClientServiceB(HttpClient client)\n",
" {\n",
" Client = client;\n",
" Console.WriteLine(\"HttpClientServiceB => 构造函数执行一次\");\n",
" }\n",
"\n",
" public async Task<string> PingAsync()\n",
" {\n",
" var response = await Client.GetAsync(\"/api/hello/Ping\");\n",
" var content = await response.Content.ReadAsStringAsync();\n",
" return content;\n",
" }\n",
"}\n",
"\n",
"{\n",
" var services = new ServiceCollection();\n",
" services.AddHttpClient<HttpClientServiceA>(client => \n",
" {\n",
" client.BaseAddress = new Uri(webApiBaseUrl);\n",
" Console.WriteLine(\"HttpClientServiceA => AddHttpClient 执行一次\");\n",
" })\n",
" .ConfigureHttpClient(client=>\n",
" {\n",
" client.Timeout = TimeSpan.FromSeconds(1);\n",
" Console.WriteLine(\"HttpClientServiceA => ConfigureHttpClient 执行一次\");\n",
" });\n",
"\n",
" services.AddHttpClient<HttpClientServiceB>(client => \n",
" {\n",
" client.BaseAddress = new Uri(webApiBaseUrl);\n",
" Console.WriteLine(\"HttpClientServiceB => AddHttpClient 执行一次\");\n",
" })\n",
" .ConfigureHttpClient(client=>\n",
" {\n",
" client.Timeout = TimeSpan.FromSeconds(2);\n",
" Console.WriteLine(\"HttpClientServiceB => ConfigureHttpClient 执行一次\");\n",
" });\n",
"\n",
" var builder = services.BuildServiceProvider();\n",
"\n",
" var serviceA = builder.GetRequiredService<HttpClientServiceA>();\n",
" var serviceB = builder.GetRequiredService<HttpClientServiceB>();\n",
" //每获取一次类型化客户端,都会执行一交。\n",
" var serviceB2 = builder.GetRequiredService<HttpClientServiceB>();\n",
"\n",
" var dataA = await serviceA.GetIndexAsync();\n",
" Console.WriteLine(dataA);\n",
"\n",
" var dataB = await serviceB.PingAsync();\n",
" Console.WriteLine(dataB);\n",
"\n",
" var dataB2 = await serviceB2.PingAsync();\n",
" Console.WriteLine(dataB2);\n",
"}\n",
"\n",
"// 类型化客户端2\n",
"{\n",
" var services = new ServiceCollection();\n",
" services.AddHttpClient<HttpClientServiceA>(client => \n",
" {\n",
" client.BaseAddress = new Uri(webApiBaseUrl);\n",
" Console.WriteLine(\"HttpClientServiceA => AddHttpClient 执行一次\");\n",
" })\n",
" .AddTypedClient<HttpClientServiceA>()\n",
" .ConfigureHttpClient(client=>\n",
" {\n",
" client.Timeout = TimeSpan.FromSeconds(1);\n",
" Console.WriteLine(\"HttpClientServiceA => ConfigureHttpClient 执行一次\");\n",
" });\n",
"}\n",
"\n",
"//todo: 生成式 HttpClient: Refit库\n",
"\n",
"/*\n",
" IFactoryHttpClient + Polly8\n",
" 1、引用库 Polly 和 Microsoft.Extensions.Http.Polly\n",
"*/\n",
"\n",
"\n"
]
},
{