深入浅出Blazor webassembly之异常错误显示

Blazor wasm 原生模版中没有提供对End user友好的异常处理机制. 一般情况下我们都需要自行实现一套自己的异常处理机制

==============================

原生的异常处理机制

==============================

Fetch.razor 的初始化代码, 加载一个不存在的json 文件, 导致程序异常, 未做特殊处理的情况.

    protected override async Task OnInitializedAsync()
    {
        forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/not_found.json");
    }

 

 

==============================

简单的JS alert处理机制

==============================

注入 IJSRuntime 调用 js alert 函数来处理异常, 对于End user 稍微好了一些, 但还是不够友好.

    [Inject] IJSRuntime Js { get; set; } 
    protected override async Task OnInitializedAsync()
    {
        try
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/not_found.json");
        }
        catch (Exception ex)
        {
            await Js.InvokeVoidAsync("alert", ex.Message);
        }

    }

 

 

 

 

==============================

自定义全局异常处理机制: Layout中内置一个全局的ErrorComponent

==============================

1. 声明一个 IErrorComponent 接口

namespace WebApplication2
{
    public interface IErrorComponent
    {
        void ShowError(string title, string message);
    }
}

2.  MainLayout.razor 实现 IErrorComponent接口, 并提供显示和关闭Error

@inherits LayoutComponentBase
@implements IErrorComponent

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <div class="main">
        <div class="top-row px-4">
            <a href="http://blazor.net" target="_blank" class="ml-md-auto">About</a>
        </div>

        <div class="content px-4">
            @if (_IsErrorActive)
            {
                <div class="alert alert-danger" role="alert">
                    <button type="button" class="close" data-dismiss="alert" aria-label="Close1" @onclick="HideError">
                        <span aria-hidden="true">&times;</span>
                    </button>  
                </div>
                <h3>@_Title</h3>
                <p>@_Message</p>
            } 

            <CascadingValue Value="this" Name="ErrorComponent">
                @Body
           </CascadingValue>
        </div>
    </div>
</div>

@code{
    bool _IsErrorActive;
    String _Title;
    String _Message;

    public void ShowError(string title, string message)
    {
        this._IsErrorActive = true;
        this._Title = title;
        this._Message = message;
        StateHasChanged();
    }

    private void HideError()
    {
        this._IsErrorActive = false;
    }
}

 

改造之前, content 部分非常简单, 代码见下, 改造之后, 在@Body 加了显示 error message的 alert 卡片.

        <div class="content px-4">
            @Body
        </div>

另外, 使用 CascadingValue 组件将 MainLayout 作为 IErrorComponent 的实例传导到各个页面中.

3. FetchData.razor 文件中, 使用 CascadingParameter 承接 IErrorComponent 实例, 并在异常点使用该实例显示出来.

    [CascadingParameter(Name = "ErrorComponent")] IErrorComponent _ErrorComponent { get; set; }
    protected override async Task OnInitializedAsync()
    {
        try
        {
            forecasts = await Http.GetFromJsonAsync<WeatherForecast[]>("sample-data/not_found.json");
        }
        catch (Exception ex)
        {
            _ErrorComponent.ShowError(ex.Message, ex.StackTrace);
        }

    }

 

效果图:

 

 

==============================

参考

==============================

https://nightbaker.github.io/gitflow/azure/piplines/2020/01/22/blazor-error-component/

https://nightbaker.github.io/blazor/exception/2021/08/11/throws-exceptions-to-blazor/

posted @ 2021-09-30 20:02  harrychinese  阅读(477)  评论(0编辑  收藏  举报