Handle Error

2022. 4. 11. 00:00ASPNET/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">&times;</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 를 다시 렌더링 하도록 한다. 

 

 

관련영상

https://youtu.be/WS9QOiVxxhY

 

 

 

반응형

'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