@elf-express/admin-net-mcp 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/dist/index.js +83 -88
  2. package/knowledge/Furion_Teaching_Manual/04-1-/351/205/215/347/275/256.md +442 -0
  3. package/knowledge/Furion_Teaching_Manual/04-2-/351/201/270/351/240/205.md +363 -0
  4. package/knowledge/Furion_Teaching_Manual/05-1-/345/213/225/346/205/213WebAPI.md +825 -0
  5. package/knowledge/Furion_Teaching_Manual/05-2-HttpContext.md +217 -0
  6. package/knowledge/Furion_Teaching_Manual/05-3-/347/257/251/351/201/270/345/231/250/346/224/224/346/210/252/345/231/250AOP.md +581 -0
  7. package/knowledge/Furion_Teaching_Manual/05-4-/350/253/213/346/261/202/347/250/275/346/240/270/346/227/245/350/252/214.md +129 -0
  8. package/knowledge/Furion_Teaching_Manual/05-5-/344/270/255/344/273/213/350/273/237/351/253/224Middleware.md +328 -0
  9. package/knowledge/Furion_Teaching_Manual/05-6-Vue-React-Angular/344/273/213/351/235/242/344/273/243/347/220/206.md +317 -0
  10. package/knowledge/Furion_Teaching_Manual/06-1/350/246/217/347/257/204/345/214/226/346/216/245/345/217/243.md +1458 -0
  11. package/knowledge/Furion_Teaching_Manual/06-2/347/254/254/344/270/211/346/226/271API_Scalar.md +91 -0
  12. package/knowledge/Furion_Teaching_Manual/07-/345/217/213/345/245/275/344/276/213/345/244/226/350/231/225/347/220/206.md +511 -0
  13. package/knowledge/Furion_Teaching_Manual/08-1-/350/263/207/346/226/231/351/251/227/350/255/211/345/237/272/347/244/216/344/275/277/347/224/250.md +587 -0
  14. package/knowledge/Furion_Teaching_Manual/10-1-SqlSugar/346/225/264/345/220/210.md +336 -0
  15. package/knowledge/Furion_Teaching_Manual/11-SaaS /345/244/232/347/247/237/346/210/266/347/255/206/350/250/230.md" +271 -0
  16. package/knowledge/Furion_Teaching_Manual/12-furion-dependency-injection.md +408 -0
  17. package/knowledge/Furion_Teaching_Manual/13-/347/211/251/344/273/266/350/263/207/346/226/231/346/230/240/345/260/204/357/274/210Mapster/357/274/211.md +162 -0
  18. package/knowledge/Furion_Teaching_Manual/14-/345/210/206/345/270/203/345/274/217/347/274/223/345/255/230.md +311 -0
  19. package/knowledge/Furion_Teaching_Manual/15-/345/256/211/345/205/250/351/211/264/346/235/203.md +832 -0
  20. package/knowledge/Furion_Teaching_Manual/17-/346/252/242/350/246/226/347/257/204/346/234/254/345/274/225/346/223/216.md +327 -0
  21. package/knowledge/Furion_Teaching_Manual/18-/346/227/245/350/252/214/350/250/230/351/214/204.md +639 -0
  22. package/knowledge/Furion_Teaching_Manual/19-1-HTTP/351/201/240/347/253/257/350/253/213/346/261/202/345/237/272/347/244/216/344/275/277/347/224/250.md +621 -0
  23. package/knowledge/Furion_Teaching_Manual/19-2-HTTP/351/201/240/347/253/257/350/253/213/346/261/202/351/200/262/351/232/216/346/214/207/345/215/227.md +928 -0
  24. package/knowledge/Furion_Teaching_Manual/19-3-HTTP/351/201/240/347/253/257/350/253/213/346/261/202/345/270/270/350/246/213/345/225/217/351/241/214.md +362 -0
  25. package/knowledge/Furion_Teaching_Manual/20-/350/263/207/346/226/231/345/212/240/350/247/243/345/257/206.md +286 -0
  26. package/knowledge/Furion_Teaching_Manual/20-/351/231/204/351/214/204-KSort/350/263/207/346/226/231/347/260/275/345/220/215/345/256/214/346/225/264/345/216/237/345/247/213/347/242/274.md +305 -0
  27. package/knowledge/Furion_Teaching_Manual/21-/345/205/250/347/220/203/345/214/226/345/222/214/346/234/254/345/234/260/345/214/226.md +342 -0
  28. package/knowledge/Furion_Teaching_Manual/22-/344/272/213/344/273/266/345/214/257/346/265/201/346/216/222EventBus.md +448 -0
  29. package/knowledge/Furion_Teaching_Manual/23-JSON/345/272/217/345/210/227/345/214/226.md +340 -0
  30. package/knowledge/Furion_Teaching_Manual/24-/345/215/263/346/231/202/351/200/232/350/250/212SignalR.md +247 -0
  31. package/knowledge/Furion_Teaching_Manual/25-/350/274/224/345/212/251/350/247/222/350/211/262/346/234/215/345/213/231WorkerService.md +295 -0
  32. package/knowledge/Furion_Teaching_Manual/26-1-/346/216/222/347/250/213/344/275/234/346/245/255/345/256/232/346/231/202/344/273/273/345/213/231.md +631 -0
  33. package/knowledge/Furion_Teaching_Manual/26-2-Cron/350/241/250/351/201/224/345/274/217.md +203 -0
  34. package/knowledge/Furion_Teaching_Manual/26-3-/344/273/273/345/213/231/344/275/207/345/210/227TaskQueue.md +215 -0
  35. package/knowledge/Furion_Teaching_Manual/27-/345/210/206/346/225/243/345/274/217ID/347/224/237/346/210/220.md +86 -0
  36. package/knowledge/Furion_Teaching_Manual/28-/346/250/241/347/265/204/345/214/226/351/226/213/347/231/274.md +68 -0
  37. package/knowledge/Furion_Teaching_Manual/29-/346/265/201/350/256/212/347/211/251/344/273/266Clay.md +313 -0
  38. package/knowledge/Furion_Teaching_Manual/30-/350/204/253/346/225/217/350/231/225/347/220/206/357/274/210Sensitive Detection).md" +168 -0
  39. package/knowledge/Furion_Teaching_Manual/32-/346/234/203/350/251/261/345/222/214/347/213/200/346/205/213/347/256/241/347/220/206.md +147 -0
  40. package/knowledge/Furion_Teaching_Manual/33-IPC/347/250/213/345/272/217/351/200/232/350/250/212.md +98 -0
  41. package/knowledge/Furion_Teaching_Manual/34-2-Docker/351/203/250/347/275/262.md +313 -0
  42. package/knowledge/Furion_Teaching_Manual/34-3-Nginx/351/203/250/347/275/262.md +157 -0
  43. package/knowledge/Furion_Teaching_Manual/34-8-WindowsService/351/203/250/347/275/262.md +112 -0
  44. package/knowledge/Furion_Teaching_Manual/35-1-Docker/347/222/260/345/242/203/346/214/201/347/272/214/351/203/250/347/275/262Jenkins.md +169 -0
  45. package/knowledge/Furion_Teaching_Manual/36-1-/345/226/256/345/205/203/346/270/254/350/251/246/346/225/264/345/220/210/346/270/254/350/251/246.md +275 -0
  46. package/knowledge/Furion_Teaching_Manual/36-3-/345/237/272/346/272/226/346/270/254/350/251/246Benchmarking.md +80 -0
  47. package/knowledge/attributes.md +153 -0
  48. package/knowledge/config.md +147 -0
  49. package/knowledge/entity.md +115 -0
  50. package/knowledge/event.md +124 -0
  51. package/knowledge/plugin.md +136 -0
  52. package/knowledge/service.md +146 -0
  53. package/knowledge/sqlsugar.md +172 -0
  54. package/knowledge/vue-typescript.md +338 -0
  55. package/package.json +3 -2
@@ -0,0 +1,91 @@
1
+ ---
2
+ title: "导语"
3
+ author: "dotNET China"
4
+ source: "https://gitee.com/dotnetchina/Furion/commit/02ba49cd3c84b13d3fc152fd1ceb084c07680029#note_49016014"
5
+ platform: "web"
6
+ extracted_at: "2026-03-17T07:37:35.976Z"
7
+ created: 2026-03-17T07:37:35.976Z
8
+ modified: 2026-03-17T07:37:35.976Z
9
+ tags: ["converted", "document", "web-extract"]
10
+ word_count: 1961
11
+ source_type: "html"
12
+ ---
13
+
14
+ **来源**:https://gitee.com/dotnetchina/Furion/commit/02ba49cd3c84b13d3fc152fd1ceb084c07680029#note_49016014
15
+ **作者**:dotNET China
16
+
17
+ ---
18
+
19
+ ## 导语
20
+
21
+ 一直以来,`Furion` 默认内置的接口文档组件为 `Swagger`,这也是框架唯一的第三方依赖。许多开发者曾尝试替换为 `Knife4jUI`,但体验仍不够理想。为此,**`Furion` 现已提供对新一代现代化文档工具 `Scalar` 的开箱支持,带来更优雅、更直观的 API 文档体验。**
22
+
23
+ ## 快速集成 Scalar 文档
24
+
25
+ [![Scalar 界面截图](https://foruda.gitee.com/images/1768500455893653516/a2887772_974299.png "Scalar 界面")](https://foruda.gitee.com/images/1768500455893653516/a2887772_974299.png)
26
+
27
+ ### 集成步骤
28
+
29
+ #### 1. 安装 NuGet 包
30
+
31
+ 在项目文件中添加 `Scalar.AspNetCore` 包引用:
32
+
33
+ ```
34
+ <ItemGroup>
35
+ <PackageReference Include="Scalar.AspNetCore" Version="2.12.8" />
36
+ </ItemGroup>
37
+ ```
38
+
39
+ #### 2. 配置中间件
40
+
41
+ 在 `Startup.cs` 或对应程序入口中,加入 `Scalar` 的映射配置:
42
+
43
+ ```
44
+ app.UseInject();
45
+
46
+
47
+
48
+ **app.UseEndpoints(endpoints =>**
49
+ - {
50
+ - endpoints.MapScalarApiReference(options =>
51
+ - {
52
+ - // options.WithTitle("项目 API 文档"); // 可自定义标题
53
+
54
+
55
+ // 自动映射所有已配置的 OpenAPI 分组
56
+ foreach (var groupInfo in SpecificationDocumentBuilder.GetOpenApiGroups())
57
+
58
+
59
+ **{**
60
+ - options.AddDocument(
61
+ - groupInfo.Group,
62
+ - groupInfo.Title,
63
+ - groupInfo.RouteTemplate
64
+ - );
65
+ - }
66
+ - });
67
+ - });
68
+
69
+ ```
70
+
71
+ #### 3. 启动访问
72
+
73
+ 运行项目后,通过以下地址即可访问 Scalar 文档界面:
74
+
75
+ > **入口地址**:`/scalar`
76
+
77
+ [![访问入口](https://foruda.gitee.com/images/1768500620064987747/c9e783eb_974299.png "入口截图")](https://foruda.gitee.com/images/1768500620064987747/c9e783eb_974299.png)
78
+ [![文档界面](https://foruda.gitee.com/images/1768500663810888333/e4d9a4aa_974299.png "文档示例")](https://foruda.gitee.com/images/1768500663810888333/e4d9a4aa_974299.png)
79
+
80
+ ---
81
+
82
+ ### 更多资源
83
+
84
+ - Scalar 官方集成文档:[https://scalar.com/products/api-references/integrations/aspnetcore/integration](https://gitee.com/link?target=https%3A%2F%2Fscalar.com%2Fproducts%2Fapi-references%2Fintegrations%2Faspnetcore%2Fintegration)
85
+ - Furion 框架文档:[查看完整指南](https://gitee.com/link?target=https%3A%2F%2Ffurion.net%2F)
86
+
87
+ [![Furion 文档截图](https://foruda.gitee.com/images/1768501430444373270/62ec5790_974299.png "Furion 文档")](https://foruda.gitee.com/images/1768501430444373270/62ec5790_974299.png)
88
+
89
+ ---
90
+
91
+ **说明**:本次集成保留了 Furion 原有的 OpenAPI 分组配置机制,仅替换了文档渲染层。开发者无需修改原有接口定义或注解,即可获得更现代的交互式文档体验。
@@ -0,0 +1,511 @@
1
+ # 7. 友好例外處理
2
+
3
+ ## 7.1 什麼是例外
4
+
5
+ 例外一般是指執行期(此處特指 `Exception` 類別)會發生的導致程式意外中止的問題,是一種對問題的描述後的封裝物件。
6
+
7
+ 在過去開發中,通常例外由系統執行時出錯拋出,但現在的開發過程中,我們應在程式開發中合理地拋出例外,比如更新一條不存在的實體,或查詢一個不存在的資料等等。
8
+
9
+ ---
10
+
11
+ ## 7.2 處理例外方式
12
+
13
+ - 不處理,直接中斷程式執行(不推薦)
14
+ - 透過 `try catch finally` 處理(不推薦)
15
+ - 全域統一處理,並記錄例外資訊(推薦)
16
+ - 例外註解方式處理,支援本地化(推薦)
17
+
18
+ ---
19
+
20
+ ## 7.3 什麼是友好例外處理
21
+
22
+ ### 7.3.1 非友好例外處理
23
+
24
+ - 對終端使用者拋出 500 狀態碼堆疊資訊
25
+ - 大量的 `try catch` 程式碼,污染正常業務邏輯
26
+ - 沒有規範化的例外狀態碼和例外訊息管理
27
+ - 沒有例外日誌收集記錄
28
+ - 不支援例外訊息本地化處理
29
+ - 不支援例外策略,失敗後程式立即終止
30
+ - 不支援分散式交易 CAP
31
+ - 不支援例外傳播
32
+ - 回傳的例外格式雜亂
33
+
34
+ ### 7.3.2 友好例外處理
35
+
36
+ - 對終端使用者提示友好
37
+ - 對後端開發人員提供詳細的例外堆疊
38
+ - 不干擾正常業務邏輯程式碼(沒有 `try catch`)
39
+ - 支援例外狀態碼多方設定
40
+ - 支援例外訊息本地化
41
+ - 例外資訊統一設定管理
42
+ - 支援例外策略,如重試
43
+ - 支援例外日誌收集記錄
44
+ - 支援 CAP 分散式交易關聯
45
+ - 支援內部例外外部傳播
46
+ - 支援回傳統一的例外格式資料
47
+
48
+ ---
49
+
50
+ ## 7.4 友好例外處理使用示例
51
+
52
+ > **小提示**:`.AddFriendlyException()` 預設已經整合在 `AddInject()` 中了,無需再次註冊。
53
+
54
+ ### 7.4.1 註冊友好例外服務
55
+
56
+ ```csharp
57
+ // Furion.Web.Core\FurWebCoreStartup.cs
58
+ using Microsoft.Extensions.DependencyInjection;
59
+
60
+ namespace Furion.Web.Core
61
+ {
62
+ [AppStartup(800)]
63
+ public sealed class FurWebCoreStartup : AppStartup
64
+ {
65
+ public void ConfigureServices(IServiceCollection services)
66
+ {
67
+ services.AddControllers()
68
+ .AddFriendlyException();
69
+ }
70
+ }
71
+ }
72
+ ```
73
+
74
+ > ⚠️ `.AddFriendlyException()` 需在 `services.AddControllers()` 之後註冊。
75
+
76
+ ### 7.4.2 兩個例子
77
+
78
+ **簡單拋個例外:**
79
+
80
+ ```csharp
81
+ using Furion.DynamicApiController;
82
+ using Furion.FriendlyException;
83
+
84
+ namespace Furion.Application
85
+ {
86
+ public class FurionAppService : IDynamicApiController
87
+ {
88
+ public int Get(int id)
89
+ {
90
+ if (id < 3)
91
+ {
92
+ throw Oops.Oh($"{id} 不能小於3");
93
+ }
94
+ return id;
95
+ }
96
+ }
97
+ }
98
+ ```
99
+
100
+ **拋出特定類型例外:**
101
+
102
+ ```csharp
103
+ public int Get(int id)
104
+ {
105
+ if (id < 3)
106
+ {
107
+ throw Oops.Oh($"{id} 不能小於3。", typeof(InvalidOperationException));
108
+ }
109
+ return id;
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## 7.5 關於 Oops.Oh
116
+
117
+ `Oops.Oh(errorMessage)` 可以結合 `throw` 拋出例外。`Oops.Oh(...)` 方法回傳的正是 `Exception` 實例。
118
+
119
+ > **為什麼起這個名字?** 來源於英語句子 "Oh, Oops!",意思是「噢(哎),出錯了!」。
120
+
121
+ ### 7.5.2 Oops.Oh 多載方法
122
+
123
+ ```csharp
124
+ public static class Oops
125
+ {
126
+ // 拋出字串例外
127
+ public static Exception Oh(string errorMessage, params object[] args);
128
+
129
+ // 拋出字串例外(指定例外類型)
130
+ public static Exception Oh(string errorMessage, Type exceptionType, params object[] args);
131
+
132
+ // 拋出錯誤碼例外
133
+ public static Exception Oh(object errorCode, params object[] args);
134
+
135
+ // 拋出錯誤碼例外(指定例外類型)
136
+ public static Exception Oh(object errorCode, Type exceptionType, params object[] args);
137
+ }
138
+ ```
139
+
140
+ ---
141
+
142
+ ## 7.6 最佳實踐 🤗
143
+
144
+ ### 7.6.1 建立例外資訊類型
145
+
146
+ 實現自訂例外資訊類型必須遵循以下設定:
147
+
148
+ - 類型必須是公開且是 `Enum` 列舉類型
149
+ - 列舉類型必須貼有 `[ErrorCodeType]` 特性
150
+ - 列舉中每一項必須貼有 `[ErrorCodeItemMetadata]` 特性
151
+
152
+ ```csharp
153
+ using Furion.FriendlyException;
154
+
155
+ namespace Furion.Application
156
+ {
157
+ [ErrorCodeType]
158
+ public enum ErrorCodes
159
+ {
160
+ [ErrorCodeItemMetadata("{0} 不能小於 {1}")]
161
+ z1000,
162
+
163
+ [ErrorCodeItemMetadata("資料不存在")]
164
+ x1000,
165
+
166
+ [ErrorCodeItemMetadata("{0} 發現 {1} 個例外", "百小僧", 2)]
167
+ x1001,
168
+
169
+ [ErrorCodeItemMetadata("伺服器執行例外", ErrorCode = "Error")]
170
+ SERVER_ERROR
171
+ }
172
+ }
173
+ ```
174
+
175
+ **巢狀錯誤訊息類型定義(Furion 4.9.7.120+):**
176
+
177
+ ```csharp
178
+ using Furion.FriendlyException;
179
+
180
+ namespace Furion.Application;
181
+
182
+ [ErrorCodeType(IncludeNestedTypes = true)]
183
+ public class ErrorCodes
184
+ {
185
+ public enum User
186
+ {
187
+ [ErrorCodeItemMetadata("{0} 不能小於 {1}")]
188
+ z1000,
189
+
190
+ [ErrorCodeItemMetadata("資料不存在")]
191
+ x1000,
192
+ }
193
+
194
+ public enum System
195
+ {
196
+ // ...
197
+ }
198
+ }
199
+ ```
200
+
201
+ ### 7.6.2 關於 [ErrorCodeItemMetadata]
202
+
203
+ `[ErrorCodeItemMetadata]` 特性用來標識列舉欄位例外中繼資料,支援傳入**訊息內容**和**格式化參數**。最終會使用 `String.Format(訊息內容, 格式化參數)` 進行格式化。
204
+
205
+ 如果訊息內容中包含格式化佔位符但未指定格式化參數,那麼會查找例外所在方法是否貼有 `[IfException]` 特性且含有格式化參數,接著查找 `Oops.Oh` 中指定的格式化參數。
206
+
207
+ ### 7.6.3 靜態例外類別使用
208
+
209
+ ```csharp
210
+ public int Get(int id)
211
+ {
212
+ if (id < 3)
213
+ {
214
+ throw Oops.Oh(ErrorCodes.z1000, id, 3);
215
+ // throw Oops.Oh(ErrorCodes.User.z1000, id, 3); // Furion 4.9.7.120+ 支援巢狀類型
216
+ }
217
+ return id;
218
+ }
219
+ ```
220
+
221
+ ### 7.6.4 例外方法重試
222
+
223
+ > **調整說明**:v2.17.0+ 版本請使用 `Retry.Invoke()` 替代。
224
+
225
+ ```csharp
226
+ Oops.Retry(() => {
227
+ // Do.....
228
+ }, 3, 1000);
229
+
230
+ // 帶回傳值
231
+ var value = Oops.Retry<int>(() => {
232
+ // Do.....
233
+ }, 3, 1000);
234
+
235
+ // 只有特定例外才監聽
236
+ Oops.Retry(() => {
237
+ // ...
238
+ }, 3, 1000, typeof(ArgumentNullException));
239
+ ```
240
+
241
+ ### 7.6.5 更多例子
242
+
243
+ ```csharp
244
+ throw Oops.Oh(1000);
245
+ throw Oops.Oh(ErrorCodes.x1000);
246
+ throw Oops.Oh("哈哈哈哈");
247
+ throw Oops.Oh(errorCode: "x1001");
248
+ throw Oops.Oh(1000, typeof(Exception));
249
+ throw Oops.Oh(1000).StatusCode(400); // 設定錯誤碼
250
+ throw Oops.Oh(1000).WithData(new Model {}); // 設定額外資料
251
+ throw Oops.Bah("使用者名稱或密碼錯誤"); // 拋出業務例外,狀態碼為 400
252
+ throw Oops.Bah(1000);
253
+ ```
254
+
255
+ ---
256
+
257
+ ## 7.7 多個例外資訊類型
258
+
259
+ ```csharp
260
+ [ErrorCodeType]
261
+ public enum ErrorCodes
262
+ {
263
+ [ErrorCodeItemMetadata("{0} 不能小於 {1}")]
264
+ z1000,
265
+
266
+ [ErrorCodeItemMetadata("資料不存在")]
267
+ x1000,
268
+ }
269
+
270
+ [ErrorCodeType]
271
+ public enum UserErrorCodes
272
+ {
273
+ [ErrorCodeItemMetadata("使用者資料不存在")]
274
+ u1000,
275
+
276
+ [ErrorCodeItemMetadata("其他例外")]
277
+ u1001
278
+ }
279
+ ```
280
+
281
+ > ⚠️ 多個例外靜態類別中也必須保證常數值唯一性,不可重複。
282
+
283
+ ---
284
+
285
+ ## 7.8 IErrorCodeTypeProvider 提供器
286
+
287
+ 在不能貼 `[ErrorCodeType]` 特性的情況下使用:
288
+
289
+ ```csharp
290
+ using Furion.FriendlyException;
291
+ using System;
292
+
293
+ namespace Furion.Application
294
+ {
295
+ public class CustomErrorCodeTypeProvider : IErrorCodeTypeProvider
296
+ {
297
+ public Type[] Definitions => new[] {
298
+ typeof(ErrorCodes),
299
+ typeof(ErrorCodes2)
300
+ };
301
+ }
302
+ }
303
+ ```
304
+
305
+ 啟用:
306
+
307
+ ```csharp
308
+ services.AddControllers()
309
+ .AddFriendlyException<CustomErrorCodeTypeProvider>();
310
+ ```
311
+
312
+ > **小知識**:只有使用 `IErrorCodeTypeProvider` 方式才需使用泛型方式註冊。透過上面的方式註冊可以同時支援 `IErrorCodeTypeProvider` 和 `[ErrorCodeType]` 方式。
313
+
314
+ ---
315
+
316
+ ## 7.9 appsettings.json 中設定
317
+
318
+ ```json
319
+ {
320
+ "ErrorCodeMessageSettings": {
321
+ "Definitions": [
322
+ ["5000", "{0} 不能小於 {1}"],
323
+ ["5001", "我叫 {0} 名字", "百小僧"],
324
+ ["5002", "Oops! 出錯了"]
325
+ ]
326
+ }
327
+ }
328
+ ```
329
+
330
+ `Definitions` 類型為二維陣列,每個陣列的第一個參數為 `ErrorCode` 錯誤碼,第二個參數為 `ErrorMessage` 訊息內容,剩餘參數作為 `ErrorMessage` 的格式化參數。
331
+
332
+ 使用示例:
333
+
334
+ ```csharp
335
+ public int Get(int id)
336
+ {
337
+ if (id < 3)
338
+ {
339
+ throw Oops.Oh(5000, id, 3);
340
+ }
341
+ return id;
342
+ }
343
+ ```
344
+
345
+ > **小知識**:`[ErrorCodeType]`、`IErrorCodeTypeProvider` 和 `appsettings.json` 可以同時使用。
346
+
347
+ ---
348
+
349
+ ## 7.10 [IfException] 使用
350
+
351
+ `[IfException]` 特性可以覆蓋預設訊息設定,也就是覆蓋例外訊息類型和 `appsettings.json` 中的設定。
352
+
353
+ > ⚠️ `[IfException]` 只能貼在方法上,支援多個。
354
+
355
+ ### 7.10.1 使用示例
356
+
357
+ ```csharp
358
+ [IfException(ErrorCodes.z1000, ErrorMessage = "我覆蓋了預設的:{0} 不能小於 {1}")]
359
+ public int Get(int id)
360
+ {
361
+ if (id < 3)
362
+ {
363
+ throw Oops.Oh(ErrorCodes.z1000, id, 3);
364
+ }
365
+ return id;
366
+ }
367
+ ```
368
+
369
+ ### 7.10.2 更多例子
370
+
371
+ ```csharp
372
+ [IfException(typeof(ExceptionType), ErrorMessage = "特定例外類型全域攔截")]
373
+ [IfException(ErrorMessage = "全域例外攔截")]
374
+ [IfException(ErrorCodes.z1000, ErrorMessage = "我覆蓋了預設的:{0} 不能小於 {1}")]
375
+ [IfException(ErrorCodes.x1001, "格式化參數1", "格式化參數2", ErrorMessage = "我覆蓋了預設的:{0} 不能小於 {1}")]
376
+ [IfException(ErrorCodes.x1000, "格式化參數1", "格式化參數2")]
377
+ [IfException(ErrorCodes.SERVER_ERROR, "格式化參數1", "格式化參數2")]
378
+ public int Get(int id)
379
+ {
380
+ if (id < 3)
381
+ {
382
+ throw Oops.Oh(ErrorCodes.z1000, id, 3);
383
+ }
384
+ return id;
385
+ }
386
+ ```
387
+
388
+ > **格式化流程**:如果訊息內容中包含格式化佔位符但未指定格式化參數,那麼會查找例外所在方法是否貼有 `[IfException]` 特性且含有格式化參數,接著查找 `Oops.Oh` 中指定的格式化參數。
389
+
390
+ ---
391
+
392
+ ## 7.11 例外訊息優先順序
393
+
394
+ ```
395
+ [ErrorCodeItemMetadata] → appsettings.json → [IfException](低 → 高)
396
+ ```
397
+
398
+ - `[IfException]` 會覆蓋 `appsettings.json` 定義的狀態碼訊息
399
+ - `appsettings.json` 會覆蓋 `[ErrorCodeItemMetadata]` 定義的訊息
400
+
401
+ ---
402
+
403
+ ## 7.12 多語言支援
404
+
405
+ 參見【全球化和本地化(多語言)】章節。
406
+
407
+ ---
408
+
409
+ ## 7.13 規範化結果例外處理
410
+
411
+ 如需自訂規範化結果可查閱【6.7 統一回傳值模型】。
412
+
413
+ ---
414
+
415
+ ## 7.14 全域例外處理提供器
416
+
417
+ 通常我們需要在例外捕獲的時候寫日誌,這時候就需要使用到 `IGlobalExceptionHandler`:
418
+
419
+ ```csharp
420
+ using Furion.DependencyInjection;
421
+ using Furion.FriendlyException;
422
+ using Microsoft.AspNetCore.Mvc.Filters;
423
+ using System.Threading.Tasks;
424
+
425
+ namespace Furion.Application
426
+ {
427
+ public class LogExceptionHandler : IGlobalExceptionHandler, ISingleton
428
+ {
429
+ public Task OnExceptionAsync(ExceptionContext context)
430
+ {
431
+ // 寫日誌
432
+ return Task.CompletedTask;
433
+ }
434
+ }
435
+ }
436
+ ```
437
+
438
+ ---
439
+
440
+ ## 7.15 FriendlyExceptionSettings 設定
441
+
442
+ | 設定項 | 類型 | 預設值 | 說明 |
443
+ |--------|------|--------|------|
444
+ | `HideErrorCode` | bool | `false` | 隱藏錯誤碼 |
445
+ | `DefaultErrorCode` | string | — | 預設錯誤碼 |
446
+ | `DefaultErrorMessage` | string | — | 預設錯誤訊息 |
447
+ | `ThrowBah` | bool | `false` | 是否將 `Oops.Oh` 預設拋出為業務例外(設定 `true` 後進入 `OnValidateFailed` 處理) |
448
+ | `LogError` | bool | `true` | 是否輸出例外日誌 |
449
+
450
+ 設定範例:
451
+
452
+ ```json
453
+ {
454
+ "FriendlyExceptionSettings": {
455
+ "DefaultErrorMessage": "系統例外,請聯繫管理員"
456
+ }
457
+ }
458
+ ```
459
+
460
+ ---
461
+
462
+ ## 7.16 BadPageResult 錯誤頁
463
+
464
+ > **版本說明**:僅限 Furion 3.6.1+ 版本使用。
465
+
466
+ Furion 內建了 `BadPageResult` 錯誤結果類型,該類型衍生自 `IActionResult`:
467
+
468
+ ```csharp
469
+ using Furion.FriendlyException;
470
+
471
+ public IActionResult Add(Person person)
472
+ {
473
+ if (!ModelState.IsValid)
474
+ {
475
+ return new BadPageResult();
476
+ }
477
+ }
478
+ ```
479
+
480
+ **BadPageResult 實例屬性和方法:**
481
+
482
+ | 屬性/方法 | 說明 |
483
+ |-----------|------|
484
+ | 建構函式 `statusCode` | 狀態碼,int 類型,預設 400 |
485
+ | `Title` | 頁面標題 |
486
+ | `Description` | 頁面描述 |
487
+ | `Code` | 詳細錯誤程式碼,支援程式碼 |
488
+ | `CodeLang` | 詳細錯誤程式碼語言,預設 `json` |
489
+ | `Base64Icon` | 頁面圖示,必須是 base64 格式 |
490
+ | `ToString()` | 將物件轉換成 HTML 字串 |
491
+ | `ToByteArray()` | 將物件轉換成 `byte[]` 陣列 |
492
+
493
+ **BadPageResult 靜態屬性:**
494
+
495
+ - `Status401Unauthorized`:輸出 401 狀態碼檢視結果
496
+ - `Status403Forbidden`:輸出 403 狀態碼檢視結果
497
+ - `Status404NotFound`:輸出 404 狀態碼檢視結果
498
+ - `Status500InternalServerError`:輸出 500 狀態碼檢視結果
499
+
500
+ ---
501
+
502
+ ## 7.17 取得錯誤碼訊息
503
+
504
+ > **版本說明**:僅限 Furion 4.9.1.18+ 版本使用。
505
+
506
+ ```csharp
507
+ var errorMessage = Oops.Text(1000); // => [1000] 錯誤訊息
508
+
509
+ // 設定第二個參數 hideErrorCode: true 可以隱藏錯誤碼
510
+ var errorMessage = Oops.Text(1000, true); // => 錯誤訊息
511
+ ```