همانطور که میدانید Blazor Server یک فریم ورک stateful است. هنگامیکه کاربران در حال تعامل با برنامه هستند، یک ارتباط پیوسته را با سرور حفظ میکنند که به آن، به اصطلاح مدار میگویند. این مدارها، کامپوننتهای فعال را به انضمام حالتهای آنها که شامل موارد زیر است نگهداری میکند:
1- جدیدترین خروجی رندر شدهی کامپوننت.
2- مجموعه Event Handlingهای جاری که میتوانند توسط کاربر صدا زده شوند.
اگر کاربری یک برنامه را در چندین تب مرورگر باز کند، در واقع چندین مدار مستقل را ایجاد کردهاست. بنابراین اگر در یکی از تبهای مرورگر استثنایی رخ دهد، مابقی تبهای مرورگر متاثر نخواهند شد.
Blazor با اکثریت استثناءهای کنترل نشده در مداری که در آن رخ میدهد، خیلی بد رفتار میکند. چرا؟
پاسخ: زیرا کاربر فقط میتواند با بارگذاری مجدد آن تب مرورگر (برای ایجاد یک مدار جدید) به تعامل با برنامه ادامه دهد.
حال برای رفع این مشکل چکار باید کرد؟ آیا راه حل سراسری برای مدیریت استثناها وجود دارد؟
پاسخ: بله.
Error boundary
یک کامپوننت از پیش تعریف شدهی Blazor است که رویکرد آسان آن برای مدیریت استثناءها به شکل زیر است:
-
هنگامیکه خطایی رخ نداده است، محتوای فرزند خود را رندر میکند.
-
هنگامیکه یک استثناء کنترل نشده رخ میدهد، صفحهی خطای پیش فرضی را رندر میکند.
برای استفاده از این کامپوننت، فقط کافی است محتوای مورد نظر خود را داخل آن بگذارید. برای مثال میتوان، برای سراسری تعریف کردن Error boundary، به شکل زیر در فایل Shared/MainLayout.razor آن را تعریف نمود:
<div>
<div>
<ErrorBoundary>
@Body
</ErrorBoundary>
</div>
</div>
در این حالت هر استثنای کنترل نشدهای که در کل برنامه رخ دهد، توسط Error boundaries کنترل شده و خطایی در صفحه نشان داده میشود. به صورت پیش فرض کامپوننت Error boundary یک div خالی را با یک کلاس css که در site.css وجود دارد، به نام
blazor-error-boundary به عنوان صفحه خطا نشان میدهد که میتوان آن را سفارشی سازی نمود. همچنین میتوان به شکل زیر نیز برای سفارشی سازی بیشتر صفحهی خطا عمل کرد:
<ErrorBoundary>
<ChildContent>
@Body
</ChildContent>
<ErrorContent>
<p class="errorUI">متاسفانه خطایی رخ داده است!</p>
</ErrorContent>
</ErrorBoundary>
به دلیل اینکه ما در این مثال Error boundary را در MainLayout تعریف کردیم، صفحهی نمایش خطا صرفنظر از اینکه کاربر به کدام صفحه رفتهاست، نمایش داده میشود. پیشنهاد مایکروسافت این است که حوزه استفاده را محدودتر کنیم.
خوب تا اینجای کار توانستیم استثنای کنترل نشده را کنترل کنیم و پیغام خطایی را نشان دهیم؛ اما همچنان صفحه در حالت خطا مانده و بازهم نیاز است که صفحه بارگذاری مجدد شود تا بتوان به صفحات دیگر برنامه رفت. آیا راه حلی وجود دارد؟
پاسخ: بله خوشبختانه. کافی است با استفاده از متد Recover کامپوننت Error boundary به شکل زیر صفحه را به حالت قبل از خطا برد:
...
<ErrorBoundary @ref="errorBoundary">
@Body
</ErrorBoundary>
...
@code {
private ErrorBoundary? errorBoundary;
protected override void OnParametersSet()
{
errorBoundary?.Recover();
}
}
در قسمت بعدی به این موضوع میپردازیم که چگونه میتوان یک کامپوننت خطای سفارشی سراسری ایجاد کرد تا علاوه بر کنترل استثناءها بتواند خطاها را نیز لاگ کند.