Skip to content

Commit 2fb6b5e

Browse files
authored
feat(ErrorLogger): redesign ErrorLogger component (#4576)
* refactor: 重构 Root 组件 * doc: 更新文档 * refactor: 重构 Root 组件 * refactor: 增加 EnableErrorLogger 开关 * refactor: 重构 Root 组件增加 EnableErrorLogger 参数 * test: 代码格式化 * refactor: 性能优化 * refactor: 更新接口 * refactor: 重构 ErrorLogger 组件 * test: 更新单元测试 * test: 增加单元测试
1 parent 6dfcef5 commit 2fb6b5e

File tree

14 files changed

+225
-225
lines changed

14 files changed

+225
-225
lines changed

src/BootstrapBlazor.Server/Components/Pages/Layout.razor

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,5 +28,3 @@ Toast: 1090;</Pre>
2828
<p>@Localizer["Para6"]</p>
2929

3030
<Button Text="@Localizer["Button"]" OnClickWithoutRender="ShowDialog"></Button>
31-
32-
<p class="mt-2">@Localizer["Footer1"] <code>Drawer</code> @Localizer["Footer2"]</p>

src/BootstrapBlazor.Server/Locales/en-US.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,9 +1723,7 @@
17231723
"Para4": "This set of components additionally",
17241724
"Para5": "The components are layered as follows",
17251725
"Para6": "test session",
1726-
"Button": "test",
1727-
"Footer1": "because",
1728-
"Footer2": "The component does not provide a service form, and it is retrofitted later"
1726+
"Button": "test"
17291727
},
17301728
"BootstrapBlazor.Server.Components.Samples.GlobalException": {
17311729
"Title": "Global exception",

src/BootstrapBlazor.Server/Locales/zh-CN.json

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1723,9 +1723,7 @@
17231723
"Para4": "本套组件额外增加了",
17241724
"Para5": "各组件分层如下",
17251725
"Para6": "测试环节",
1726-
"Button": "测试",
1727-
"Footer1": "由于",
1728-
"Footer2": "组件未提供服务形式,后期改造"
1726+
"Button": "测试"
17291727
},
17301728
"BootstrapBlazor.Server.Components.Samples.GlobalException": {
17311729
"Title": "全局异常",

src/BootstrapBlazor/Components/BaseComponents/BootstrapBlazorRoot.razor

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,25 @@
11
@inherits ComponentBase
22
@namespace BootstrapBlazor.Components
33

4-
@RenderBody()
4+
<CascadingValue Value="this" IsFixed="true">
5+
<ErrorLogger EnableErrorLogger="EnableErrorLoggerValue" ShowToast="ShowToast" ToastTitle="@ToastTitle" OnErrorHandleAsync="OnErrorHandleAsync!">
6+
@ChildContent
57

6-
<Message @ref="MessageContainer"></Message>
7-
<ToastContainer @ref="ToastContainer"></ToastContainer>
8-
<DrawerContainer></DrawerContainer>
8+
<Dialog></Dialog>
9+
<DrawerContainer></DrawerContainer>
10+
<SweetAlert></SweetAlert>
11+
<Message @ref="MessageContainer"></Message>
12+
<ToastContainer @ref="ToastContainer"></ToastContainer>
913

10-
<ConnectionHub></ConnectionHub>
11-
<Mask></Mask>
14+
<Download></Download>
15+
<Mask></Mask>
16+
<Print></Print>
17+
<ConnectionHub></ConnectionHub>
1218

13-
@foreach (var com in Generators)
14-
{
15-
@com.Generator()
16-
}
19+
@foreach (var com in Generators)
20+
{
21+
@com.Generator()
22+
}
23+
</ErrorLogger>
24+
</CascadingValue>
1725

18-
@code {
19-
RenderFragment RenderChildContent =>
20-
@<CascadingValue Value="this" IsFixed="true">
21-
@ChildContent
22-
</CascadingValue>;
23-
}

src/BootstrapBlazor/Components/BaseComponents/BootstrapBlazorRoot.razor.cs

Lines changed: 0 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -78,66 +78,4 @@ public override async Task SetParametersAsync(ParameterView parameters)
7878

7979
await base.SetParametersAsync(parameters);
8080
}
81-
82-
private RenderFragment RenderBody() => builder =>
83-
{
84-
if (EnableErrorLoggerValue)
85-
{
86-
builder.OpenComponent<ErrorLogger>(0);
87-
builder.AddAttribute(1, nameof(ErrorLogger.ShowToast), ShowToast);
88-
builder.AddAttribute(2, nameof(ErrorLogger.ToastTitle), ToastTitle);
89-
if (OnErrorHandleAsync != null)
90-
{
91-
builder.AddAttribute(3, nameof(ErrorLogger.OnErrorHandleAsync), OnErrorHandleAsync);
92-
}
93-
builder.AddAttribute(4, nameof(ErrorLogger.ChildContent), RenderContent);
94-
builder.CloseComponent();
95-
}
96-
else
97-
{
98-
builder.AddContent(0, RenderContent);
99-
}
100-
};
101-
102-
private static RenderFragment RenderComponents() => builder =>
103-
{
104-
builder.OpenComponent<Dialog>(0);
105-
builder.CloseComponent();
106-
107-
builder.OpenComponent<SweetAlert>(2);
108-
builder.CloseComponent();
109-
110-
builder.OpenComponent<Print>(3);
111-
builder.CloseComponent();
112-
113-
builder.OpenComponent<Download>(4);
114-
builder.CloseComponent();
115-
};
116-
117-
private RenderFragment RenderContent => builder =>
118-
{
119-
#if NET8_0_OR_GREATER
120-
builder.AddContent(0, RenderChildContent);
121-
builder.AddContent(1, RenderComponents());
122-
#else
123-
Render();
124-
125-
[ExcludeFromCodeCoverage]
126-
void Render()
127-
{
128-
if (OperatingSystem.IsBrowser())
129-
{
130-
builder.AddContent(0, RenderChildContent);
131-
builder.AddContent(1, RenderComponents());
132-
}
133-
else
134-
{
135-
builder.OpenElement(0, "app");
136-
builder.AddContent(1, RenderChildContent);
137-
builder.CloseElement();
138-
builder.AddContent(2, RenderComponents());
139-
}
140-
}
141-
#endif
142-
};
14381
}

src/BootstrapBlazor/Components/BaseComponents/BootstrapComponentBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ private async Task CallStateHasChangedOnAsyncCompletion(Task task)
5252
return;
5353
}
5454

55-
if (ErrorLogger != null)
55+
if (ErrorLogger is { EnableErrorLogger: true })
5656
{
5757
IsNotRender = true;
5858
await ErrorLogger.HandlerExceptionAsync(ex);
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the Apache 2.0 License
3+
// See the LICENSE file in the project root for more information.
4+
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone
5+
6+
using Microsoft.AspNetCore.Components.Rendering;
7+
using Microsoft.Extensions.Configuration;
8+
using Microsoft.Extensions.Logging;
9+
10+
namespace BootstrapBlazor.Components;
11+
12+
/// <summary>
13+
/// 内部使用 自定义异常组件
14+
/// </summary>
15+
class BootstrapBlazorErrorBoundary : ErrorBoundaryBase
16+
{
17+
[Inject]
18+
[NotNull]
19+
private ILogger<ErrorLogger>? Logger { get; set; }
20+
21+
[Inject]
22+
[NotNull]
23+
private IConfiguration? Configuration { get; set; }
24+
25+
[Inject]
26+
[NotNull]
27+
private ToastService? ToastService { get; set; }
28+
29+
/// <summary>
30+
/// 获得/设置 自定义错误处理回调方法
31+
/// </summary>
32+
[Parameter]
33+
public Func<ILogger, Exception, Task>? OnErrorHandleAsync { get; set; }
34+
35+
/// <summary>
36+
/// 获得/设置 是否显示弹窗 默认 true 显示
37+
/// </summary>
38+
[Parameter]
39+
public bool ShowToast { get; set; } = true;
40+
41+
/// <summary>
42+
/// 获得/设置 Toast 弹窗标题
43+
/// </summary>
44+
[Parameter]
45+
[NotNull]
46+
public string? ToastTitle { get; set; }
47+
48+
/// <summary>
49+
/// <inheritdoc/>
50+
/// </summary>
51+
/// <param name="exception"></param>
52+
/// <returns></returns>
53+
/// <exception cref="NotImplementedException"></exception>
54+
protected override async Task OnErrorAsync(Exception exception)
55+
{
56+
// 由框架调用
57+
if (OnErrorHandleAsync != null)
58+
{
59+
await OnErrorHandleAsync(Logger, exception);
60+
}
61+
else
62+
{
63+
if (ShowToast)
64+
{
65+
await ToastService.Error(ToastTitle, exception.Message);
66+
}
67+
68+
Logger.LogError(exception, "{BootstrapBlazorErrorBoundary} {OnErrorAsync} log this error", nameof(BootstrapBlazorErrorBoundary), nameof(OnErrorAsync));
69+
}
70+
}
71+
72+
/// <summary>
73+
/// <inheritdoc/>
74+
/// </summary>
75+
/// <param name="builder"></param>
76+
protected override void BuildRenderTree(RenderTreeBuilder builder)
77+
{
78+
if (OnErrorHandleAsync == null)
79+
{
80+
var ex = CurrentException ?? _exception;
81+
if (ex != null)
82+
{
83+
builder.AddContent(0, ExceptionContent(ex));
84+
}
85+
}
86+
builder.AddContent(1, ChildContent);
87+
}
88+
89+
private Exception? _exception = null;
90+
91+
private RenderFragment<Exception> ExceptionContent => ex => builder =>
92+
{
93+
if (ErrorContent != null)
94+
{
95+
builder.AddContent(0, ErrorContent(ex));
96+
}
97+
else
98+
{
99+
var index = 0;
100+
builder.OpenElement(index++, "div");
101+
builder.AddAttribute(index++, "class", "error-stack");
102+
builder.AddContent(index++, ex.FormatMarkupString(Configuration.GetEnvironmentInformation()));
103+
builder.CloseElement();
104+
}
105+
};
106+
107+
/// <summary>
108+
/// 渲染异常信息方法
109+
/// </summary>
110+
/// <param name="exception"></param>
111+
/// <param name="handler"></param>
112+
public async Task RenderException(Exception exception, IHandlerException? handler)
113+
{
114+
await OnErrorAsync(exception);
115+
116+
if (handler != null)
117+
{
118+
await handler.HandlerException(exception, ExceptionContent);
119+
}
120+
else
121+
{
122+
_exception = exception;
123+
StateHasChanged();
124+
}
125+
}
126+
}

0 commit comments

Comments
 (0)