2022. 4. 11. 00:00ㆍASPNET/Blazor
처리되지 않은 예외
다음과 같은 이유로 인해 처리되지 않은 예외가 발생하면 프레임워크가 회로를 종료합니다.
- 처리되지 않은 예외는 종종 회로를 정의되지 않은 상태로 둡니다.
- 처리되지 않은 예외가 발생한 후에는 앱의 일반 작업을 보장할 수 없습니다.
- 회로가 정의되지 않은 상태로 계속되는 경우 앱에 보안 취약성이 나타날 수 있습니다.
ErrorBoundary 를 통한 Error 처리
Shared/MainLayout.razor:
<div class="main">
<div class="content px-4">
<ErrorBoundary>
@Body
</ErrorBoundary>
</div>
</div>
Pages/Counter.razor의 경우
private void IncrementCount()
{
currentCount++;
if (currentCount > 5)
{
throw new InvalidOperationException("Current count is too big!");
}
}
실행하면 currentCount 가 5 이상이 될때 error 를 발생 시킴
그러면 화면에 다음과 같은 에러가 표시됨
이후 왼쪽 sidebar (navmenu) 를 눌러도 해당 error 만 표시됨
그리고 가끔은 SignalR 을 disconnect 함 (원래는 항상 해야 한다)
Reload 를 시키면 원상태로 현재 상태에서 화면을 refresh 한다.
그래서 Reload 를 하지 않고 Connection disconnected 하지 않는 방법이 필요함
Shared/MainLayout.razor 아래에 @code 블록을 추가함
... html 및 razor 구문
...
<ErrorBoundary @ref="_errorBoundary">
@Body
</ErrorBoundary>
@code{
private ErrorBoundary? _errorBoundary;
protected override void OnParametersSet()
{
_errorBoundary?.Recover();
}
}
이후에 다른 sidebar 의 다른 menu 를 클릭하거나 같은 메뉴를 다시 클릭하면 초기화된 정상화면을 볼 수 있다.
사용자 정의 Error Component 를 통해 CascadingValue 에 error 전달하여 error 처리
Shared/Error.razor
@using Microsoft.Extensions.Logging
@inject ILogger<Error> Logger
<div>
@if (isErrorActive)
{
<div class="alert alert-danger" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close" @onclick="HideError">
<span aria-hidden="true">×</span>
</button>
<h3>@title</h3>
<p>@message</p>
</div>
}
<CascadingValue Value="this">
@ChildContent
</CascadingValue>
</div>
@code {
[Parameter]
public RenderFragment? ChildContent { get; set; }
bool isErrorActive=false;
string title;
string message;
public void ProcessError(Exception ex)
{
string message = $"Error:ProcessError - Type: {ex.GetType()} Message: {ex.Message}";
Logger.LogError(message);
this.isErrorActive = true;
this.title = "Error:ProcessError";
this.message = message;
StateHasChanged();
}
private void HideError()
{
isErrorActive = false;
}
}
App.razor
<Error>
<Router AppAssembly="@typeof(App).Assembly">
<Found Context="routeData">
<RouteView RouteData="@routeData" DefaultLayout="@typeof(MainLayout)" />
<FocusOnNavigate RouteData="@routeData" Selector="h1" />
</Found>
<NotFound>
<PageTitle>Not found</PageTitle>
<LayoutView Layout="@typeof(MainLayout)">
<p role="alert">Sorry, there's nothing at this address.</p>
</LayoutView>
</NotFound>
</Router>
</Error>
Pages/RaisedErrorRazor.razor
@page "/raised-error-razor"
<PageTitle>RaisedErrorRazor</PageTitle>
<h1>RaisedErrorRazor</h1>
<p role="status">Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
[CascadingParameter]
public Error? Error { get; set; }
private void IncrementCount()
{
try
{
currentCount++;
if (currentCount > 5)
{
throw new InvalidOperationException("Current count is too big!");
}
}
catch (Exception ex)
{
Error?.ProcessError(ex);
}
}
}
logger 를 통해 console 에도 error 를 표시하고
Error.razor 를 통해 화면에도 error 를 표시한다.
ProcessErrors 에서 메서드의 끝에 StateHasChanged() 를 호출하여 UI 를 다시 렌더링 하도록 한다.
관련영상
'ASPNET > Blazor' 카테고리의 다른 글
Layout (0) | 2022.04.13 |
---|---|
Component Lifecycle (구성 요소 수명 주기 ) (0) | 2022.04.12 |
Logging (0) | 2022.04.08 |
Startup (0) | 2022.04.07 |
Dependency injection (종속성 주입) (0) | 2022.04.06 |