diff --git a/Docs/1.0项目管理.dib b/Docs/1.0项目管理.dib index 114cf1c..de9f77c 100644 --- a/Docs/1.0项目管理.dib +++ b/Docs/1.0项目管理.dib @@ -1,6 +1,6 @@ #!meta -{"kernelInfo":{"defaultKernelName":"csharp","items":[{"aliases":[],"languageName":"csharp","name":"csharp"}]}} +{"kernelInfo":{"defaultKernelName":"csharp","items":[{"name":"csharp","languageName":"csharp"},{"name":"fsharp","languageName":"F#","aliases":["f#","fs"]},{"name":"html","languageName":"HTML"},{"name":"http","languageName":"HTTP"},{"name":"javascript","languageName":"JavaScript","aliases":["js"]},{"name":"mermaid","languageName":"Mermaid"},{"name":"pwsh","languageName":"PowerShell","aliases":["powershell"]},{"name":"value"}]}} #!markdown diff --git a/Docs/1.2.使用准则.ipynb b/Docs/1.2.使用准则.ipynb index c9ffd6a..bfcc833 100644 --- a/Docs/1.2.使用准则.ipynb +++ b/Docs/1.2.使用准则.ipynb @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 21, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -38,39 +38,43 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/markdown": [ + "## 初始化\n", + "这是全局共用文件,包括Nuget包引用、全局类库引用、全局文件引用、全局命名空间引用、全局变量、全局方法、全局类定义等功能。\n", + "\n", + "在业务笔记中引用,执行其它单元格之前先执行一次。" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Installed Packages
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "程序[d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!\n", + "已启动WebApi项目,保持窗口打开状态!\n", + "初始化完成!\n" + ] + } + ], "source": [ - "//全局设置\n", - "#r \"./Publish/HttpClientStudy.Core/HttpClientStudy.Core.dll\"\n", - "\n", - "//全局命名空间引用\n", - "global using System.Net;\n", - "global using System.Net.Http;\n", - "global using System.Diagnostics;\n", - "global using System.Collections;\n", - "global using System.Text;\n", - "global using System.Linq;\n", - "global using System.IO;\n", - "global using System.Threading;\n", - "global using System.Threading.Tasks;\n", - "\n", - "global using HttpClientStudy.Core;\n", - "global using HttpClientStudy.Core.Utilities;\n", - "\n", - "//全局共享变量\n", - "var global_api_config = HttpClientStudy.Config.WebApiConfigManager.GetWebApiConfig();\n", - "var global_ips = Dns.GetHostAddresses(global_api_config.Host);\n", - "var global_queryIp = global_ips.First().ToString();\n", - "if(global_api_config.Host.Contains(\"localhost\"))\n", - "{\n", - " global_queryIp = \"127.0.0.1\";\n", - "}\n", - "var global_default_page = $\"{global_api_config.PathBase}/Normal/GetAllAccounts\";\n", - "//启动WebAPI程序\n", - "var global_netstat_filter = $\"{global_queryIp}:{global_api_config.Port}\";\n", - "var global_webapi_file = Path.GetFullPath(\"./Publish/HttpClientStudy.WebApp/HttpClientStudy.WebApp.exe\", Environment.CurrentDirectory); \n", - "var message = AppUtility.RunWebApiExeFile(global_webapi_file);\n", - "Console.WriteLine(message);" + "//初始化:必须先执行一次\n", + "#!import ./ini.ipynb" ] }, { @@ -82,7 +86,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 22, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -94,7 +98,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "http://127.0.0.1:5189\r\n" + ] + } + ], "source": [ "{ //大括号: 1、作用域隔离 2、方便整体代码折叠\n", " Console.WriteLine(global_api_config.BaseUrl);\n", @@ -110,7 +122,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 23, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -141,7 +153,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 24, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -153,7 +165,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "HttpClientStudy.WebApp 进程已退出\r\n" + ] + } + ], "source": [ "# 关闭项目进程\n", "$WebAppProcName =\"HttpClientStudy.WebApp\";\n", @@ -190,7 +210,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -202,7 +222,48 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
System.Net.Http.HttpClient
DefaultRequestHeaders
[ ]
Accept
[ ]
Count
0
IsReadOnly
False
(values)(empty)
AcceptCharset
[ ]
Count
0
IsReadOnly
False
(values)(empty)
AcceptEncoding
[ ]
Count
0
IsReadOnly
False
(values)(empty)
AcceptLanguage
[ ]
Count
0
IsReadOnly
False
(values)(empty)
Authorization
<null>
ExpectContinue
<null>
From
<null>
Host
<null>
IfMatch
[ ]
Count
0
IsReadOnly
False
(values)(empty)
IfModifiedSince
<null>
IfNoneMatch
[ ]
Count
0
IsReadOnly
False
(values)(empty)
IfRange
<null>
IfUnmodifiedSince
<null>
MaxForwards
<null>
Protocol
<null>
ProxyAuthorization
<null>
Range
<null>
Referrer
<null>
TE
[ ]
Count
0
IsReadOnly
False
(values)(empty)
UserAgent
[ ]
Count
0
IsReadOnly
False
(values)(empty)
Expect
[ ]
Count
0
IsReadOnly
False
(values)(empty)
CacheControl
<null>
Connection
[ ]
Count
0
IsReadOnly
False
(values)
[  ]
ConnectionClose
<null>
Date
<null>
Pragma
[ ]
Count
0
IsReadOnly
False
(values)(empty)
Trailer
[ ]
Count
0
IsReadOnly
False
(values)
[  ]
TransferEncoding
[ ]
Count
0
IsReadOnly
False
(values)(empty)
TransferEncodingChunked
<null>
Upgrade
[ ]
Count
0
IsReadOnly
False
(values)(empty)
Via
[ ]
Count
0
IsReadOnly
False
(values)(empty)
Warning
[ ]
Count
0
IsReadOnly
False
(values)(empty)
NonValidated
[ ]
Count
0
(values)(empty)
(values)(empty)
DefaultRequestVersion
1.1
Major
1
Minor
1
Build
-1
Revision
-1
MajorRevision
-1
MinorRevision
-1
DefaultVersionPolicyRequestVersionOrLower
BaseAddress
<null>
Timeout00:01:40
MaxResponseContentBufferSize
2147483647
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "using System.Net.Http;\n", "{\n", @@ -281,7 +342,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -293,7 +354,48 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
System.Net.Http.HttpClient
DefaultRequestHeaders
[ ]
Accept
[ ]
Count
0
IsReadOnly
False
(values)(empty)
AcceptCharset
[ ]
Count
0
IsReadOnly
False
(values)(empty)
AcceptEncoding
[ ]
Count
0
IsReadOnly
False
(values)(empty)
AcceptLanguage
[ ]
Count
0
IsReadOnly
False
(values)(empty)
Authorization
<null>
ExpectContinue
<null>
From
<null>
Host
<null>
IfMatch
[ ]
Count
0
IsReadOnly
False
(values)(empty)
IfModifiedSince
<null>
IfNoneMatch
[ ]
Count
0
IsReadOnly
False
(values)(empty)
IfRange
<null>
IfUnmodifiedSince
<null>
MaxForwards
<null>
Protocol
<null>
ProxyAuthorization
<null>
Range
<null>
Referrer
<null>
TE
[ ]
Count
0
IsReadOnly
False
(values)(empty)
UserAgent
[ ]
Count
0
IsReadOnly
False
(values)(empty)
Expect
[ ]
Count
0
IsReadOnly
False
(values)(empty)
CacheControl
<null>
Connection
[ ]
Count
0
IsReadOnly
False
(values)
[  ]
ConnectionClose
<null>
Date
<null>
Pragma
[ ]
Count
0
IsReadOnly
False
(values)(empty)
Trailer
[ ]
Count
0
IsReadOnly
False
(values)
[  ]
TransferEncoding
[ ]
Count
0
IsReadOnly
False
(values)(empty)
TransferEncodingChunked
<null>
Upgrade
[ ]
Count
0
IsReadOnly
False
(values)(empty)
Via
[ ]
Count
0
IsReadOnly
False
(values)(empty)
Warning
[ ]
Count
0
IsReadOnly
False
(values)(empty)
NonValidated
[ ]
Count
0
(values)(empty)
(values)(empty)
DefaultRequestVersion
1.1
Major
1
Minor
1
Build
-1
Revision
-1
MajorRevision
-1
MinorRevision
-1
DefaultVersionPolicyRequestVersionOrLower
BaseAddress
<null>
Timeout00:01:40
MaxResponseContentBufferSize
2147483647
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "//手动配置 SocketsHttpHandler\n", "{\n", @@ -327,7 +429,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -339,7 +441,24 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "程序运行大约要10-20秒,请在程序退出后,执行下面命令行查看网络情况\r\n" + ] + }, + { + "data": { + "text/plain": [ + "第5次请求完成" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "//测试连接寿命\n", "{\n", @@ -388,7 +507,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 37, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -400,7 +519,16 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "请先执行上面的单元,再执行本单元\n", + "网络状态\n" + ] + } + ], "source": [ "# 若查询不到,则异常\n", "#!set --value @csharp:global_netstat_filter --name queryFilter\n", @@ -420,7 +548,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -432,7 +560,36 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "程序运行大约要10-20,请在程序退出后,执行下面命令行查看网络情况\r\n" + ] + }, + { + "data": { + "text/plain": [ + "第5次请求完成" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TCP 127.0.0.1:45262 127.0.0.1:5189 TIME_WAIT 0\r\n", + " TCP 127.0.0.1:45269 127.0.0.1:5189 TIME_WAIT 0\r\n", + " TCP 127.0.0.1:45274 127.0.0.1:5189 TIME_WAIT 0\r\n", + " TCP 127.0.0.1:45283 127.0.0.1:5189 TIME_WAIT 0\r\n", + " TCP 127.0.0.1:45296 127.0.0.1:5189 TIME_WAIT 0\r\n", + "\r\n" + ] + } + ], "source": [ "//程序池设置\n", "{ \n", @@ -490,7 +647,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -502,7 +659,19 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TCP 127.0.0.1:45262 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45269 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45274 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45283 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45296 127.0.0.1:5189 TIME_WAIT 0\n" + ] + } + ], "source": [ "#!set --value @csharp:global_netstat_filter --name queryFilter\n", "netstat -ano | findstr $queryFilter" @@ -524,7 +693,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 40, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -536,7 +705,27 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "开始请求网络...\n", + "共请求了200次,耗时 55 毫秒\n", + "当前网络状态\n", + " TCP 127.0.0.1:5189 127.0.0.1:45299 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45300 ESTABLISHED 42312\n", + " TCP 127.0.0.1:45262 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45269 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45274 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45283 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45296 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45299 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45300 127.0.0.1:5189 ESTABLISHED 37024\n", + "\n" + ] + } + ], "source": [ "/*\n", "\t功能:将MaxConnectionsPerServer限制为2。然后启动200个任务,每个任务都向同一端点发出HTTP请求。这些任务将同时运行。所有请求竞争所花费的时间将写入控制台。\n", @@ -575,7 +764,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 41, "metadata": { "dotnet_interactive": { "language": "pwsh" @@ -587,7 +776,23 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + " TCP 127.0.0.1:5189 127.0.0.1:45299 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45300 ESTABLISHED 42312\n", + " TCP 127.0.0.1:45262 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45269 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45274 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45283 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45296 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45299 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45300 127.0.0.1:5189 ESTABLISHED 37024\n" + ] + } + ], "source": [ "# 重新查询当前网络状态\n", "#!set --value @csharp:global_netstat_filter --name queryFilter\n", @@ -603,7 +808,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 42, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -615,7 +820,47 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "开始请求网络...\n", + "共请求了200次,耗时 39 毫秒\n", + "当前网络状态\n", + " TCP 127.0.0.1:5189 127.0.0.1:45299 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45300 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45307 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45308 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45309 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45310 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45311 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45312 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45313 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45314 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45315 ESTABLISHED 42312\n", + " TCP 127.0.0.1:5189 127.0.0.1:45316 ESTABLISHED 42312\n", + " TCP 127.0.0.1:45262 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45269 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45274 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45283 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45296 127.0.0.1:5189 TIME_WAIT 0\n", + " TCP 127.0.0.1:45299 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45300 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45307 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45308 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45309 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45310 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45311 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45312 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45313 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45314 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45315 127.0.0.1:5189 ESTABLISHED 37024\n", + " TCP 127.0.0.1:45316 127.0.0.1:5189 ESTABLISHED 37024\n", + "\n" + ] + } + ], "source": [ "{ //MaxConnectionsPerServer 设置为10:网络连接将增加到10个,耗时将减少到1/4\n", "\tConsole.WriteLine(\"开始请求网络...\");\n", @@ -687,7 +932,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 43, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -740,7 +985,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 44, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -752,7 +997,24 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "共有1195个字符\r\n" + ] + } + ], "source": [ "#r \"nuget:Polly\"\n", "#r \"nuget:Microsoft.Extensions.Http.Resilience\"\n", diff --git a/Docs/1.3.0.基础使用.管理客户端.ipynb b/Docs/1.3.0.基础使用.管理客户端.ipynb index 2eb75b0..1ea8e7d 100644 --- a/Docs/1.3.0.基础使用.管理客户端.ipynb +++ b/Docs/1.3.0.基础使用.管理客户端.ipynb @@ -32,7 +32,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 25, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -44,77 +44,44 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], - "source": [ - "//全局设置,行运行一次,为后续准备\n", - "#r \"nuget:System.Net.Http.Json\"\n", - "#r \"nuget:Microsoft.Net.Http.Headers\"\n", - "#r \"nuget:Microsoft.Extensions.Http\"\n", - "#r \"nuget:Microsoft.Extensions.DependencyInjection\"\n", - "#r \"nuget:Microsoft.Extensions.Logging\" \n", - "#r \"nuget:Microsoft.Extensions.Logging.Console\"\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", - "global using System.IO;\n", - "global using System.IO.Enumeration;\n", - "global using System.Buffers;\n", - "\n", - "global using System.Collections;\n", - "global using System.Collections.Concurrent;\n", - "global using System.Linq;\n", - "global using System.Linq.Expressions;\n", - "global using System.Threading;\n", - "global using System.Threading.Tasks;\n", - "\n", - "global using System.Net.Http;\n", - "global using System.Net.Http.Json;\n", - "\n", - "global using Microsoft.Extensions.DependencyInjection;\n", - "global using Microsoft.Extensions.DependencyInjection.Extensions;\n", - "global using Microsoft.Extensions.Logging;\n", - "global using Microsoft.Extensions.Logging.Console;\n", - "global using Microsoft.Extensions.Http.Logging;\n", - "\n", - "\n", - "global using Polly;\n", - "global using Polly.NoOp;\n", - "global using Polly.Simmy;\n", - "global using Polly.Retry;\n", - "global using Polly.Hedging;\n", - "global using Polly.Timeout;\n", - "global using Polly.Bulkhead;\n", - "global using Polly.Fallback;\n", - "global using Polly.RateLimit;\n", - "global using Polly.CircuitBreaker;\n", - "global using Polly.Utilities;\n", - "global using Polly.Extensions;\n", - "global using Polly.Wrap;\n", - "global using Polly.Registry;\n", - "global using Polly.Telemetry;\n", - "global using Polly.Extensions.Http;\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", - "//全局变量\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", - "\n", - "//启动已发布的WebApi项目\n", - "Console.WriteLine(\"启动WebApi项目\");\n", - "var startMessage = AppUtility.RunWebApiExeFile(fullPath);\n", - "Console.WriteLine(startMessage);\n" + "outputs": [ + { + "data": { + "text/markdown": [ + "## 初始化\n", + "这是全局共用文件,包括Nuget包引用、全局类库引用、全局文件引用、全局命名空间引用、全局变量、全局方法、全局类定义等功能。\n", + "\n", + "在业务笔记中引用,执行其它单元格之前先执行一次。" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Installed Packages
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "启动WebApi项目...\n", + "程序[d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!\n", + "已启动WebApi项目,保持窗口打开状态!\n", + "初始化完成!\n" + ] + } + ], + "source": [ + "//初始化:必须先执行一次\n", + "#!import ./ini.ipynb" ] }, { @@ -152,7 +119,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 26, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -164,7 +131,24 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\r\n" + ] + }, + { + "data": { + "text/plain": [ + "第 10 次/ 共 10 次请求,成功!" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "/*\n", " 每次请求都实例化:并发量大、请求频繁进会耗尽套接字端口\n", @@ -217,7 +201,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 27, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -229,7 +213,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "{\"data\":{\"host\":\"localhost\",\"port\":5189,\"scheme\":\"http\",\"pathBase\":\"\",\"baseUrl\":\"http://localhost:5189\",\"webAppMutexName\":\"HttpClientStudy.WebApp\"},\"code\":1,\"message\":\"成功\"}\n", + "{\"data\":[{\"id\":1,\"name\":\"管理员01\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":2,\"name\":\"管理员02\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":3,\"name\":\"管理员03\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":4,\"name\":\"管理员04\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":5,\"name\":\"管理员05\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":6,\"name\":\"管理员06\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":7,\"name\":\"管理员07\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":8,\"name\":\"管理员08\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":9,\"name\":\"管理员09\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":10,\"name\":\"管理员10\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":11,\"name\":\"开发01\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":12,\"name\":\"开发01\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":13,\"name\":\"开发03\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":14,\"name\":\"开发04\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":15,\"name\":\"开发05\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":16,\"name\":\"开发06\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":17,\"name\":\"开发07\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":18,\"name\":\"开发08\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":19,\"name\":\"开发09\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":20,\"name\":\"开发10\",\"password\":\"123456\",\"role\":\"Dev\"}],\"code\":1,\"message\":\"成功\"}\n" + ] + } + ], "source": [ "/*\n", " 静态类/属性\n", @@ -286,7 +280,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 28, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -298,7 +292,18 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "HttpClientSingleton 初始化一次\n", + "{\"data\":{\"host\":\"localhost\",\"port\":5189,\"scheme\":\"http\",\"pathBase\":\"\",\"baseUrl\":\"http://localhost:5189\",\"webAppMutexName\":\"HttpClientStudy.WebApp\"},\"code\":1,\"message\":\"成功\"}\n", + "{\"data\":[{\"id\":1,\"name\":\"管理员01\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":2,\"name\":\"管理员02\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":3,\"name\":\"管理员03\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":4,\"name\":\"管理员04\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":5,\"name\":\"管理员05\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":6,\"name\":\"管理员06\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":7,\"name\":\"管理员07\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":8,\"name\":\"管理员08\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":9,\"name\":\"管理员09\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":10,\"name\":\"管理员10\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":11,\"name\":\"开发01\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":12,\"name\":\"开发01\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":13,\"name\":\"开发03\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":14,\"name\":\"开发04\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":15,\"name\":\"开发05\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":16,\"name\":\"开发06\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":17,\"name\":\"开发07\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":18,\"name\":\"开发08\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":19,\"name\":\"开发09\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":20,\"name\":\"开发10\",\"password\":\"123456\",\"role\":\"Dev\"}],\"code\":1,\"message\":\"成功\"}\n" + ] + } + ], "source": [ "/*\n", " 单例实现1:\n", @@ -371,7 +376,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 29, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -383,7 +388,18 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "HttpClientSingleton2 初始化一次\n", + "{\"data\":{\"host\":\"localhost\",\"port\":5189,\"scheme\":\"http\",\"pathBase\":\"\",\"baseUrl\":\"http://localhost:5189\",\"webAppMutexName\":\"HttpClientStudy.WebApp\"},\"code\":1,\"message\":\"成功\"}\n", + "{\"data\":[{\"id\":1,\"name\":\"管理员01\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":2,\"name\":\"管理员02\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":3,\"name\":\"管理员03\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":4,\"name\":\"管理员04\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":5,\"name\":\"管理员05\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":6,\"name\":\"管理员06\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":7,\"name\":\"管理员07\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":8,\"name\":\"管理员08\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":9,\"name\":\"管理员09\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":10,\"name\":\"管理员10\",\"password\":\"123456\",\"role\":\"Admin\"},{\"id\":11,\"name\":\"开发01\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":12,\"name\":\"开发01\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":13,\"name\":\"开发03\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":14,\"name\":\"开发04\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":15,\"name\":\"开发05\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":16,\"name\":\"开发06\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":17,\"name\":\"开发07\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":18,\"name\":\"开发08\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":19,\"name\":\"开发09\",\"password\":\"123456\",\"role\":\"Dev\"},{\"id\":20,\"name\":\"开发10\",\"password\":\"123456\",\"role\":\"Dev\"}],\"code\":1,\"message\":\"成功\"}\n" + ] + } + ], "source": [ "/*\n", " 单例实现2:\n", @@ -478,7 +494,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 30, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -490,7 +506,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "403252\r\n" + ] + } + ], "source": [ "// 百度服务类\n", "public sealed class BaiduService \n", @@ -532,7 +556,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 31, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -544,7 +568,16 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "{\"data\":\"操作成功\",\"code\":1,\"message\":\"成功\"}\n" + ] + } + ], "source": [ "// 本机服务类\n", "// 百度服务类\n", @@ -594,7 +627,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 32, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -606,7 +639,28 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "内部重试\n", + "内部重试\n", + "内部重试\n", + "Response status code does not indicate success: 500 (Internal Server Error).\n" + ] + } + ], "source": [ "#r \"nuget:Polly\"\n", "#r \"nuget:Microsoft.Extensions.Http.Polly\"\n", @@ -673,7 +727,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 33, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -685,7 +739,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "227\n", + "227\n", + "18\n" + ] + } + ], "source": [ "/*\n", " 注意:\n", @@ -749,7 +813,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 34, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -761,7 +825,16 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "A: 227\n", + "A: 18\n" + ] + } + ], "source": [ "// IoC 多个HttpClient服务类\n", "\n", @@ -865,7 +938,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 35, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -877,7 +950,43 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/plain": [ + "Index" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Pong" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Pong" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "没有参数的配置:AddHttpClient(),因后续配置中,赋值 BaseAddress 不起使用,出现异常:\r\n", + "An invalid request URI was provided. Either the request URI must be an absolute URI or BaseAddress must be set.\r\n" + ] + } + ], "source": [ "//方式1:默认客户端\n", "{ \n", @@ -1005,7 +1114,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 36, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1017,7 +1126,19 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "ConfigureHttpClientDefaults 只执行一次!\n", + "Pong\n", + "ConfigureHttpClient 每次 CreateClient 执行一次!\n", + "Hello, world!\n", + "ConfigureHttpClient 每次 CreateClient 执行一次!\n" + ] + } + ], "source": [ "//全局配置:所有HttpClient配置\n", "{\n", @@ -1085,7 +1206,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 37, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1097,7 +1218,33 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Pong\r\n" + ] + }, + { + "data": { + "text/plain": [ + "Pong" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/plain": [ + "Pong" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "//命名客户端\n", "{\n", @@ -1172,7 +1319,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 38, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1184,7 +1331,40 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "方式1 -------------------------------------------------------------------\n", + "HttpClientServiceA => 构造函数执行一次\n", + "HttpClientServiceB => 构造函数执行一次\n", + "Index\n", + "Pong\n", + "========================================================================\n", + "方式2 -------------------------------------------------------------------\n", + "HttpClientServiceA => 构造函数执行一次\n", + "HttpClientServiceB => 构造函数执行一次\n", + "Index\n", + "Pong\n", + "========================================================================\n", + "方式3 -------------------------------------------------------------------\n", + "HttpClientServiceA => AddHttpClient 执行一次\n", + "HttpClientServiceA => ConfigureHttpClient 执行一次\n", + "HttpClientServiceA => 构造函数执行一次\n", + "HttpClientServiceB => AddHttpClient 执行一次\n", + "HttpClientServiceB => ConfigureHttpClient 执行一次\n", + "HttpClientServiceB => 构造函数执行一次\n", + "HttpClientServiceB => AddHttpClient 执行一次\n", + "HttpClientServiceB => ConfigureHttpClient 执行一次\n", + "HttpClientServiceB => 构造函数执行一次\n", + "Index\n", + "Pong\n", + "Pong\n", + "========================================================================\n" + ] + } + ], "source": [ "// 类型化客户端 HttpClient\n", "public class HttpClientServiceA\n", @@ -1335,7 +1515,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 39, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1347,7 +1527,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "LoggerDelegatingHandler -> SendAsync -> Before\n", + "LoggerDelegatingHandler -> SendAsync -> After\n", + "Pong\n" + ] + } + ], "source": [ "//管道配置\n", "\n", @@ -1430,7 +1620,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 40, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1442,7 +1632,20 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "info: logger[0]\n", + " 直接使用的通用日志!\n", + "info: logger[0]\n", + " IoC中使用日志!\n", + "fail: logger[0]\n", + " IoC中的错误日志!\n" + ] + } + ], "source": [ "//通用日志\n", "{\n", @@ -1484,7 +1687,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 41, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1496,7 +1699,47 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "info: System.Net.Http.HttpClient.Default.LogicalHandler[100]\n", + " Start processing HTTP request GET http://127.0.0.1:5189/api/hello/index\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[102]\n", + " Request Headers:\n", + " Authorization: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[100]\n", + " Sending HTTP request GET http://127.0.0.1:5189/api/hello/index\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[102]\n", + " Request Headers:\n", + " Authorization: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[101]\n", + " Received HTTP response headers after 1.8609ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[101]\n", + " End processing HTTP request after 2.0736ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "Index\n" + ] + } + ], "source": [ "//配置默认日志(必须有常规日志及级别设置,否则不起使用)\n", "{\n", @@ -1560,7 +1803,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 42, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1572,7 +1815,21 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "自定义日志:GET http://127.0.0.1:5189/api/hello/index - 200 OK in 1.9399ms\n", + "API 影响内容:Index\n", + "info: Submission#44.RequestIdLogger[1]\n", + " Request Id=3b7f07e7-1069-4c05-beb0-a7c7c9dc5e39 (127.0.0.1) started\n", + "info: Submission#44.RequestIdLogger[2]\n", + " Request Id=3b7f07e7-1069-4c05-beb0-a7c7c9dc5e39 succeeded in 3.6723ms\n", + "API 影响内容:Hello, world!\n" + ] + } + ], "source": [ "/* 添加自定义日志记录\n", " 1、可以指定当 HttpClient 启动请求、接收响应或引发异常时记录的内容和方式。可以同时添加多个自定义记录器(控制台、ETW 记录器),或“包装”和“不包装”记录器。由于其附加性质,可能需要事先显式删除默认的“旧”日志记录。\n", @@ -1776,7 +2033,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 43, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1788,7 +2045,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "响应内容:32\r\n" + ] + } + ], "source": [ "/*\n", " 便捷应用:AddTransientHttpErrorPolicy() 方法,添加常用瞬时错误重试策略\n", @@ -1838,7 +2103,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 44, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1850,7 +2115,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "未处理的异常:The operation has been rate-limited and should be retried after 00:00:02.3122931\r\n" + ] + } + ], "source": [ "/*\n", " 传统方式配置Polly策略\n", @@ -1938,7 +2211,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 45, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -1950,7 +2223,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "13\r\n" + ] + } + ], "source": [ "{\n", " var services = new ServiceCollection();\n", @@ -1998,7 +2279,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 46, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -2010,7 +2291,16 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Hello, world!\n", + "Post Success\n" + ] + } + ], "source": [ "//实质是AddPolicyHandler中选择一个策略\n", "{\n", @@ -2053,7 +2343,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 47, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -2065,7 +2355,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Response status code does not indicate success: 500 (Internal Server Error).\r\n" + ] + } + ], "source": [ "{\n", " var registry = new PolicyRegistry()\n", @@ -2120,7 +2418,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -2132,7 +2430,266 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "info: System.Net.Http.HttpClient.Default.LogicalHandler[100]\n", + " Start processing HTTP request GET http://127.0.0.1:5189/api/hello/ping\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "TokenDelegatingHandler -> SendAsync -> Before\n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[100]\n", + " Sending HTTP request GET http://127.0.0.1:5189/api/hello/ping\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[101]\n", + " Received HTTP response headers after 1.9645ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "自定义日志:GET http://127.0.0.1:5189/api/hello/ping - 200 OK in 2.187ms\n", + "TokenDelegatingHandler -> SendAsync -> After\n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[101]\n", + " End processing HTTP request after 5.0129ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "Pong\n", + "TokenDelegatingHandler -> SendAsync -> Before\n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[100]\n", + " Start processing HTTP request GET http://127.0.0.1:5189/api/polly8/hello\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[100]\n", + " Sending HTTP request GET http://127.0.0.1:5189/api/polly8/hello\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[101]\n", + " Received HTTP response headers after 0.7798ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "自定义日志:GET http://127.0.0.1:5189/api/polly8/hello - 200 OK in 0.9376ms\n", + "TokenDelegatingHandler -> SendAsync -> After\n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[101]\n", + " End processing HTTP request after 5.0396ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "Polly v8\n", + "TokenDelegatingHandler -> SendAsync -> Before\n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[100]\n", + " Start processing HTTP request GET http://127.0.0.1:5189/api/Hello/Ping\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[100]\n", + " Sending HTTP request GET http://127.0.0.1:5189/api/Hello/Ping\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "自定义日志:GET http://127.0.0.1:5189/api/Hello/Ping - 200 OK in 2.7059ms\n", + "TokenDelegatingHandler -> SendAsync -> After\n", + "Pong\n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[101]\n", + " Received HTTP response headers after 2.5729ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[101]\n", + " End processing HTTP request after 3.6811ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "TokenDelegatingHandler -> SendAsync -> Before\n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[100]\n", + " Start processing HTTP request GET http://127.0.0.1:5189/api/Hello/Index\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[100]\n", + " Sending HTTP request GET http://127.0.0.1:5189/api/Hello/Index\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[101]\n", + " Received HTTP response headers after 1.3795ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "自定义日志:GET http://127.0.0.1:5189/api/Hello/Index - 200 OK in 1.4913ms\n", + "TokenDelegatingHandler -> SendAsync -> After\n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[101]\n", + " End processing HTTP request after 15.0227ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "Index\n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[100]\n", + " Start processing HTTP request GET http://127.0.0.1:5189/api/Hello/Get\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "TokenDelegatingHandler -> SendAsync -> Before\n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[100]\n", + " Sending HTTP request GET http://127.0.0.1:5189/api/Hello/Get\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[101]\n", + " Received HTTP response headers after 0.932ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "自定义日志:GET http://127.0.0.1:5189/api/Hello/Get - 200 OK in 1.0696ms\n", + "TokenDelegatingHandler -> SendAsync -> After\n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[101]\n", + " End processing HTTP request after 16.068ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "Hello, world!\n", + "TokenDelegatingHandler -> SendAsync -> Before\n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[100]\n", + " Start processing HTTP request POST http://127.0.0.1:5189/api/Hello/Post\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[100]\n", + " Sending HTTP request POST http://127.0.0.1:5189/api/Hello/Post\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "info: System.Net.Http.HttpClient.Default.ClientHandler[101]\n", + " Received HTTP response headers after 1.3516ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.ClientHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "自定义日志:POST http://127.0.0.1:5189/api/Hello/Post - 200 OK in 1.5213ms\n", + "TokenDelegatingHandler -> SendAsync -> After\n", + "info: System.Net.Http.HttpClient.Default.LogicalHandler[101]\n", + " End processing HTTP request after 13.8899ms - 200\n", + "trce: System.Net.Http.HttpClient.Default.LogicalHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "Post Success\n", + "info: System.Net.Http.HttpClient.ClientA.LogicalHandler[100]\n", + " Start processing HTTP request GET http://127.0.0.1:5189/api/Polly8/Hello\n", + "trce: System.Net.Http.HttpClient.ClientA.LogicalHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "TokenDelegatingHandler -> SendAsync -> Before\n", + "info: System.Net.Http.HttpClient.ClientA.ClientHandler[100]\n", + " Sending HTTP request GET http://127.0.0.1:5189/api/Polly8/Hello\n", + "trce: System.Net.Http.HttpClient.ClientA.ClientHandler[102]\n", + " Request Headers:\n", + " X-Custom-Demo: *\n", + " \n", + "info: System.Net.Http.HttpClient.ClientA.ClientHandler[101]\n", + " Received HTTP response headers after 4.6109ms - 200\n", + "trce: System.Net.Http.HttpClient.ClientA.ClientHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n", + "自定义日志:GET http://127.0.0.1:5189/api/Polly8/Hello - 200 OK in 4.8865ms\n", + "TokenDelegatingHandler -> SendAsync -> After\n", + "info: System.Net.Http.HttpClient.ClientA.LogicalHandler[101]\n", + " End processing HTTP request after 9.3018ms - 200\n", + "Polly v8\n", + "trce: System.Net.Http.HttpClient.ClientA.LogicalHandler[103]\n", + " Response Headers:\n", + " Date: *\n", + " Server: *\n", + " Transfer-Encoding: *\n", + " X-WebApi-UseTime: *\n", + " Content-Type: *\n", + " \n" + ] + } + ], "source": [ "/* 综合示例1\n", " 工厂 + 类型化客户端 + 管道 + Polly + 日志(自定义) \n", diff --git a/Docs/1.3.1.基础使用.发送请求.ipynb b/Docs/1.3.1.基础使用.发送请求.ipynb index 60ee79c..61035d6 100644 --- a/Docs/1.3.1.基础使用.发送请求.ipynb +++ b/Docs/1.3.1.基础使用.发送请求.ipynb @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 48, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -45,51 +45,44 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], - "source": [ - "//全局设置,行运行一次,为后续准备\n", - "//#r \"nuget:Microsoft.Net.Http.Headers,8.0.12\"\n", - "//#r \"nuget:Microsoft.Extensions.Http,8.0.1\"\n", - "//#r \"nuget:System.Net.Http.Json,8.0.1\"\n", - "//#r \"nuget:Microsoft.Extensions.DependencyInjection,8.0.1\"\n", - "#r \"./Publish/HttpClientStudy.Model/HttpClientStudy.Model.dll\"\n", - "#r \"./Publish/HttpClientStudy.Core/HttpClientStudy.Core.dll\"\n", - "\n", - "global using System;\n", - "global using System.Collections;\n", - "global using System.Collections.Concurrent;\n", - "global using System.Linq;\n", - "global using System.Linq.Expressions;\n", - "global using System.Threading;\n", - "global using System.Threading.Tasks;\n", - "global using System.Net.Http;\n", - "//System.Net.Http.Json 包含处理json的扩展方法,方便处理请求和影响中的json数据\n", - "global using System.Net.Http.Json;\n", - "global using Microsoft.Extensions.DependencyInjection;\n", - "global using Microsoft.Extensions.DependencyInjection.Extensions;\n", - "\n", - "global using HttpClientStudy.Config;\n", - "global using HttpClientStudy.Model;\n", - "global using HttpClientStudy.Core;\n", - "global using HttpClientStudy.Core.Utilities;\n", - "\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", - "\n", - "//全局共享静态 HttpClient 对象\n", - "public static HttpClient SharedClient = new HttpClient(new SocketsHttpHandler(){ PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30)})\n", - "{\n", - " BaseAddress = new Uri(WebApiConfigManager.GetWebApiConfig().BaseUrl),\n", - "};\n", - "\n", - "//启动已发布的WebApi项目\n", - "{\n", - " Console.WriteLine(\"启动WebApi项目\");\n", - " var startMessage = AppUtility.RunWebApiExeFile(fullPath);\n", - " Console.WriteLine(startMessage);\n", - "}" + "outputs": [ + { + "data": { + "text/markdown": [ + "## 初始化\n", + "这是全局共用文件,包括Nuget包引用、全局类库引用、全局文件引用、全局命名空间引用、全局变量、全局方法、全局类定义等功能。\n", + "\n", + "在业务笔记中引用,执行其它单元格之前先执行一次。" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.Extensions.DependencyInjection, 9.0.3
  • Microsoft.Extensions.Http, 9.0.3
  • Microsoft.Extensions.Http.Polly, 9.0.3
  • Microsoft.Extensions.Logging, 9.0.3
  • Microsoft.Extensions.Logging.Console, 9.0.3
  • Microsoft.Net.Http.Headers, 9.0.3
  • Polly, 8.5.2
  • Refit, 8.0.0
  • Refit.HttpClientFactory, 8.0.0
  • System.Net.Http.Json, 9.0.3
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "启动WebApi项目...\n", + "程序[d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!\n", + "已启动WebApi项目,保持窗口打开状态!\n", + "初始化完成!\n" + ] + } + ], + "source": [ + "//初始化:必须先执行一次\n", + "#!import ./ini.ipynb" ] }, { @@ -261,7 +254,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 49, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -273,7 +266,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Index\r\n" + ] + } + ], "source": [ "//Get 请求\n", "{\n", @@ -308,7 +309,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 50, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -320,7 +321,128 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/html": [ + "
HttpClientStudy.Model.Account
Id
1
Name
Hello
Password
pwd
Role
Devlopment
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
HttpClientStudy.Model.Account
Id
1
Name
Hello
Password
pwd
Role
Devlopment
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
HttpClientStudy.Model.Account
Id
0
Name
<null>
Password
<null>
Role
Dev
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "/*\n", " 方式一:使用 System.Net.Http.Json\n", @@ -378,7 +500,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 51, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -390,7 +512,16 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Post Success\n", + "添加成功\n" + ] + } + ], "source": [ "//不带请求体\n", "{\n", @@ -438,7 +569,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 52, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -450,7 +581,55 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"data\":{\"id\":2,\"name\":\"管理员02\",\"password\":\"123456\",\"role\":\"Admin\"},\"code\":1,\"message\":\"成功\"}\r\n" + ] + }, + { + "data": { + "text/html": [ + "
HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]
Data
HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]
Code
1
Message
成功
Data
HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "/* Put请求, 一般是添加或修改资源:需要数据。\n", " 这里故意使用查询,没有资源:\n", @@ -488,7 +667,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 53, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -500,7 +679,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "无响应体\r\n" + ] + } + ], "source": [ "//Head请求,借助SendAsync方法\n", "{\n", @@ -532,7 +719,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 54, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -544,7 +731,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"data\":{\"id\":1,\"name\":\"Patch更新\",\"password\":\"123456\",\"role\":\"Admin\"},\"code\":1,\"message\":\"成功\"}\r\n" + ] + } + ], "source": [ "//Patch请求\n", "{\n", @@ -581,7 +776,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 55, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -593,7 +788,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"data\":1,\"code\":1,\"message\":\"成功\"}\r\n" + ] + } + ], "source": [ "//Delete 删除资源\n", "{\n", @@ -622,7 +825,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 56, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -634,7 +837,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"data\":\"简单OPTIONS请求\",\"code\":1,\"message\":\"成功\"}\r\n" + ] + } + ], "source": [ "//Options 预检请求\n", "{\n", @@ -666,7 +877,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 57, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -678,7 +889,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "我是请求内容\r\n" + ] + } + ], "source": [ "//trace 服务器已设置专门中间件支持所有接口的Trace请求\n", "{\n", diff --git a/Docs/1.3.2.基础使用.使用请求数据.ipynb b/Docs/1.3.2.基础使用.使用请求数据.ipynb index a382aa2..0754421 100644 --- a/Docs/1.3.2.基础使用.使用请求数据.ipynb +++ b/Docs/1.3.2.基础使用.使用请求数据.ipynb @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -45,50 +45,44 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "data": { + "text/markdown": [ + "## 初始化\n", + "这是全局共用文件,包括Nuget包引用、全局类库引用、全局文件引用、全局命名空间引用、全局变量、全局方法、全局类定义等功能。\n", + "\n", + "在业务笔记中引用,执行其它单元格之前先执行一次。" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.Extensions.DependencyInjection, 9.0.3
  • Microsoft.Extensions.Http, 9.0.3
  • Microsoft.Extensions.Http.Polly, 9.0.3
  • Microsoft.Extensions.Logging, 9.0.3
  • Microsoft.Extensions.Logging.Console, 9.0.3
  • Microsoft.Net.Http.Headers, 9.0.3
  • Polly, 8.5.2
  • Refit, 8.0.0
  • Refit.HttpClientFactory, 8.0.0
  • System.Net.Http.Json, 9.0.3
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "启动WebApi项目...\n", + "程序[d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!\n", + "已启动WebApi项目,保持窗口打开状态!\n", + "初始化完成!\n" + ] + } + ], "source": [ - "//初始化,只执行一次\n", - "\n", - "// 引用nuget包和类库文件\n", - "//#r \"nuget:Microsoft.Net.Http.Headers,8.0.12\"\n", - "//#r \"nuget:Microsoft.Extensions.Http,8.0.1\"\n", - "//#r \"nuget:System.Net.Http.Json,8.0.1\"\n", - "#r \"./Publish/HttpClientStudy.Model/HttpClientStudy.Model.dll\"\n", - "#r \"./Publish/HttpClientStudy.Core/HttpClientStudy.Core.dll\"\n", - "\n", - "//全局引用\n", - "global using System;\n", - "global using System.Collections;\n", - "global using System.Linq;\n", - "global using System.Linq.Expressions;\n", - "global using System.Threading;\n", - "global using System.Threading.Tasks;\n", - "global using System.Net.Http;\n", - "global using System.Net.Mime;\n", - "global using System.Net.Http.Json;\n", - "\n", - "global using HttpClientStudy.Config;\n", - "global using HttpClientStudy.Model;\n", - "global using HttpClientStudy.Core;\n", - "global using HttpClientStudy.Core.Utilities;\n", - "\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", - "\n", - "//全局共享静态 HttpClient 对象\n", - "public static HttpClient SharedClient = new HttpClient(new SocketsHttpHandler(){ PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30)})\n", - "{\n", - " BaseAddress = new Uri(WebApiConfigManager.GetWebApiConfig().BaseUrl),\n", - "};\n", - "\n", - "//启动已发布的WebApi项目\n", - "{\n", - " Console.WriteLine(\"启动WebApi项目\");\n", - " var startMessage = AppUtility.RunWebApiExeFile(fullPath);\n", - " Console.WriteLine(startMessage);\n", - "}" + "//初始化:必须先执行一次\n", + "#!import ./ini.ipynb" ] }, { @@ -107,7 +101,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 2, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -119,7 +113,96 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "{\"data\":{\"id\":1,\"name\":\"管理员01\",\"password\":\"123456\",\"role\":\"Admin\"},\"code\":1,\"message\":\"成功\"}\n" + ] + }, + { + "data": { + "text/html": [ + "
HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]
Data
HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]
Code
1
Message
成功
Data
HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]
Data
HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]
Code
1
Message
成功
Data
HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], "source": [ "/**\n", " URL传参:适合简单数据类型\n", @@ -167,7 +250,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 3, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -179,7 +262,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"data\":{\"id\":1,\"name\":\"管理员01\",\"password\":\"123456\",\"role\":\"Admin\"},\"code\":1,\"message\":\"成功\"}\r\n" + ] + } + ], "source": [ "/*\n", "** 路由参数:参数是URL的一部分,由后端指定\n", @@ -215,7 +306,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 4, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -227,7 +318,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"data\":{\"id\":1,\"name\":\"管理员01\",\"password\":\"123456\",\"role\":\"Admin\"},\"code\":1,\"message\":\"成功\"}\r\n" + ] + } + ], "source": [ "/*\n", "* 请求头: 值必须是字符串,如果有中文等需进行编码\n", @@ -305,7 +404,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 5, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -317,7 +416,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\"data\":\"Id=1&name=管理员01\",\"code\":1,\"message\":\"成功\"}\r\n" + ] + } + ], "source": [ "/*\n", "* Form表单,提交数据。一般为Put或Post提交。\n", @@ -384,7 +491,7 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 7, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -396,7 +503,15 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\r\n" + ] + } + ], "source": [ "/*\n", " \n", diff --git a/Docs/1.3.3.基础使用.处理响应.ipynb b/Docs/1.3.3.基础使用.处理响应.ipynb index f90bd83..049344e 100644 --- a/Docs/1.3.3.基础使用.处理响应.ipynb +++ b/Docs/1.3.3.基础使用.处理响应.ipynb @@ -33,7 +33,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 1, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -46,59 +46,43 @@ } }, "outputs": [ + { + "data": { + "text/markdown": [ + "## 初始化\n", + "这是全局共用文件,包括Nuget包引用、全局类库引用、全局文件引用、全局命名空间引用、全局变量、全局方法、全局类定义等功能。\n", + "\n", + "在业务笔记中引用,执行其它单元格之前先执行一次。" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.Extensions.DependencyInjection, 9.0.3
  • Microsoft.Extensions.Http, 9.0.3
  • Microsoft.Extensions.Http.Polly, 9.0.3
  • Microsoft.Extensions.Logging, 9.0.3
  • Microsoft.Extensions.Logging.Console, 9.0.3
  • Microsoft.Net.Http.Headers, 9.0.3
  • Polly, 8.5.2
  • Refit, 8.0.0
  • Refit.HttpClientFactory, 8.0.0
  • System.Net.Http.Json, 9.0.3
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, { "name": "stdout", "output_type": "stream", "text": [ - "配置文件根目录:c:\\Users\\ruyu\\Desktop\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", - "启动WebApi项目\n", - "程序[c:\\Users\\ruyu\\Desktop\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!\n" + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "启动WebApi项目...\n", + "程序[d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!\n", + "已启动WebApi项目,保持窗口打开状态!\n", + "初始化完成!\n" ] } ], "source": [ - "//初始化,只执行一次\n", - "\n", - "// 引用nuget包和类库文件\n", - "#r \"./Publish/HttpClientStudy.Model/HttpClientStudy.Model.dll\"\n", - "#r \"./Publish/HttpClientStudy.Core/HttpClientStudy.Core.dll\"\n", - "\n", - "//全局引用\n", - "global using System;\n", - "global using System.Collections;\n", - "global using System.Linq;\n", - "global using System.Linq.Expressions;\n", - "global using System.Threading;\n", - "global using System.Threading.Tasks;\n", - "global using System.Net.Http;\n", - "global using System.Net.Mime;\n", - "global using System.Net.Http.Json;\n", - "\n", - "global using Microsoft.Extensions.DependencyInjection;\n", - "global using Microsoft.Extensions.DependencyInjection.Extensions;\n", - "\n", - "global using HttpClientStudy.Config;\n", - "global using HttpClientStudy.Model;\n", - "global using HttpClientStudy.Core;\n", - "global using HttpClientStudy.Core.Utilities;\n", - "\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", - "\n", - "//全局共享静态 HttpClient 对象\n", - "public static HttpClient SharedClient = new HttpClient(new SocketsHttpHandler(){ PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30)})\n", - "{\n", - " BaseAddress = new Uri(WebApiConfigManager.GetWebApiConfig().BaseUrl),\n", - "};\n", - "\n", - "//启动已发布的WebApi项目\n", - "{\n", - " Console.WriteLine(\"启动WebApi项目\");\n", - " var startMessage = AppUtility.RunWebApiExeFile(fullPath);\n", - " Console.WriteLine(startMessage);\n", - "}" + "//初始化:必须先执行一次\n", + "#!import ./ini.ipynb" ] }, { @@ -110,7 +94,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 2, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -127,6 +111,7 @@ "name": "stdout", "output_type": "stream", "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", "响应码正常:{\"data\":{\"id\":1,\"name\":\"管理员01\",\"password\":\"123456\",\"role\":\"Admin\"},\"code\":1,\"message\":\"成功\"}\n", "响应码异常:状态码 BadRequest\n", "响应正常:内容为 HttpClientStudy.Model.BaseResult`1[HttpClientStudy.Model.Account]\n", @@ -221,7 +206,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 3, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -279,7 +264,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -392,7 +377,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -480,12 +465,17 @@ "languageId": "polyglot-notebook" } }, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "响应内容:28\r\n" + ] + } + ], "source": [ "//Polly进行异常处理\n", - "#r \"nuget:Polly,8.5.1\"\n", - "#r \"nuget:Microsoft.Extensions.Http.Polly,8.0.12\"\n", - "using Polly;\n", "var services = new ServiceCollection();\n", "services.AddHttpClient(string.Empty)\n", " //配置默认命名客户端\n", @@ -527,7 +517,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 12, "metadata": { "dotnet_interactive": { "language": "csharp" @@ -545,7 +535,7 @@ "output_type": "stream", "text": [ "响应头:\n", - "Date = Fri, 17 Jan 2025 02:32:12 GMT\n", + "Date = Fri, 04 Apr 2025 08:13:51 GMT\n", "Server = Kestrel\n", "Transfer-Encoding = chunked\n", "X-WebApi-UseTime = 0\n" diff --git a/Docs/Ini.ipynb b/Docs/Ini.ipynb new file mode 100644 index 0000000..e5a2f2c --- /dev/null +++ b/Docs/Ini.ipynb @@ -0,0 +1,164 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 初始化\n", + "这是全局共用文件,包括Nuget包引用、全局类库引用、全局文件引用、全局命名空间引用、全局变量、全局方法、全局类定义等功能。\n", + "\n", + "在业务笔记中引用,执行其它单元格之前先执行一次。" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "polyglot_notebook": { + "kernelName": "csharp" + } + }, + "outputs": [ + { + "data": { + "text/html": [ + "
Installed Packages
  • Microsoft.Extensions.DependencyInjection, 9.0.3
  • Microsoft.Extensions.Http, 9.0.3
  • Microsoft.Extensions.Http.Polly, 9.0.3
  • Microsoft.Extensions.Logging, 9.0.3
  • Microsoft.Extensions.Logging.Console, 9.0.3
  • Microsoft.Net.Http.Headers, 9.0.3
  • Polly, 8.5.2
  • Refit, 8.0.0
  • Refit.HttpClientFactory, 8.0.0
  • System.Net.Http.Json, 9.0.3
" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "配置文件根目录:d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.Core\n", + "启动WebApi项目...\n", + "程序[d:\\软件项目\\学习项目\\HttpClientStudy\\Docs\\Publish\\HttpClientStudy.WebApp\\HttpClientStudy.WebApp.exe]已在新的命令行窗口执行。如果未出现新命令行窗口,可能是程序错误造成窗口闪现!\n", + "已启动WebApi项目,保持窗口打开状态!\n", + "初始化完成!\n" + ] + } + ], + "source": [ + "//全局设置,行运行一次,为后续准备\n", + "#r \"nuget:System.Net.Http.Json\"\n", + "#r \"nuget:Microsoft.Net.Http.Headers\"\n", + "#r \"nuget:Microsoft.Extensions.Http\"\n", + "#r \"nuget:Microsoft.Extensions.DependencyInjection\"\n", + "#r \"nuget:Microsoft.Extensions.Logging\" \n", + "#r \"nuget:Microsoft.Extensions.Logging.Console\"\n", + "#r \"nuget:Polly\"\n", + "#r \"nuget:Microsoft.Extensions.Http.Polly\"\n", + "#r \"nuget:Refit, 8.0.0\" \n", + "#r \"nuget:Refit.HttpClientFactory, 8.0.0\"\n", + "#r \"./Publish/HttpClientStudy.Model/HttpClientStudy.Model.dll\"\n", + "#r \"./Publish/HttpClientStudy.Core/HttpClientStudy.Core.dll\"\n", + "\n", + "//全局命名空间引用\n", + "global using System;\n", + "global using System.Buffers;\n", + "global using System.Collections;\n", + "global using System.Collections.Concurrent;\n", + "global using System.Diagnostics;\n", + "global using System.IO;\n", + "global using System.IO.Enumeration;\n", + "global using System.Linq;\n", + "global using System.Linq.Expressions;\n", + "global using System.Net;\n", + "global using System.Net.Http;\n", + "global using System.Net.Http.Json;\n", + "global using System.Text;\n", + "global using System.Threading;\n", + "global using System.Threading.Tasks;\n", + "\n", + "global using Microsoft.Extensions.DependencyInjection;\n", + "global using Microsoft.Extensions.DependencyInjection.Extensions;\n", + "global using Microsoft.Extensions.Logging;\n", + "global using Microsoft.Extensions.Logging.Console;\n", + "global using Microsoft.Extensions.Http.Logging;\n", + "\n", + "global using Polly;\n", + "global using Polly.NoOp;\n", + "global using Polly.Simmy;\n", + "global using Polly.Retry;\n", + "global using Polly.Hedging;\n", + "global using Polly.Timeout;\n", + "global using Polly.Bulkhead;\n", + "global using Polly.Fallback;\n", + "global using Polly.RateLimit;\n", + "global using Polly.CircuitBreaker;\n", + "global using Polly.Utilities;\n", + "global using Polly.Extensions;\n", + "global using Polly.Wrap;\n", + "global using Polly.Registry;\n", + "global using Polly.Telemetry;\n", + "global using Polly.Extensions.Http;\n", + "\n", + "global using Refit;\n", + "//global using Refit.HttpClientFactory;\n", + "\n", + "global using HttpClientStudy.Model;\n", + "global using HttpClientStudy.Config;\n", + "global using HttpClientStudy.Core;\n", + "global using HttpClientStudy.Core.Utilities;\n", + "\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", + "\n", + "//全局共享变量\n", + "var global_api_config = HttpClientStudy.Config.WebApiConfigManager.GetWebApiConfig();\n", + "var global_ips = Dns.GetHostAddresses(global_api_config.Host);\n", + "var global_queryIp = global_ips.First().ToString();\n", + "if(global_api_config.Host.Contains(\"localhost\"))\n", + "{\n", + " global_queryIp = \"127.0.0.1\";\n", + "}\n", + "var global_default_page = $\"{global_api_config.PathBase}/Normal/GetAllAccounts\";\n", + "\n", + "//全局共享静态 HttpClient 对象\n", + "public static HttpClient SharedClient = new HttpClient(new SocketsHttpHandler(){ PooledConnectionIdleTimeout = TimeSpan.FromSeconds(30)})\n", + "{\n", + " BaseAddress = new Uri(WebApiConfigManager.GetWebApiConfig().BaseUrl),\n", + "};\n", + "\n", + "//启动已发布的WebApi项目\n", + "{\n", + " Console.WriteLine(\"启动WebApi项目...\");\n", + " var global_netstat_filter = $\"{global_queryIp}:{global_api_config.Port}\";\n", + " var global_webapi_file = Path.GetFullPath(\"./Publish/HttpClientStudy.WebApp/HttpClientStudy.WebApp.exe\", Environment.CurrentDirectory); \n", + " var message = AppUtility.RunWebApiExeFile(global_webapi_file);\n", + " Console.WriteLine(message);\n", + " Console.WriteLine(\"已启动WebApi项目,保持窗口打开状态!\");\n", + "}\n", + "\n", + "Console.WriteLine(\"初始化完成!\");" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": ".NET (C#)", + "language": "C#", + "name": ".net-csharp" + }, + "polyglot_notebook": { + "kernelInfo": { + "defaultKernelName": "csharp", + "items": [ + { + "aliases": [], + "languageName": "csharp", + "name": "csharp" + } + ] + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}