اولین Middleware موجود در بستهی Microsoft.AspNetCore.Diagnostics را در مطلب «
ارتقاء به ASP.NET Core 1.0 - قسمت 3 - Middleware چیست؟» با نمایش welcome page آن، بررسی کردیم. در این مطلب سایر صفحات مخصوص توسعه دهندههای موجود در این بسته را مرور خواهیم کرد.
مشاهدهی جزئیات اطلاعات سرور و بستههای نصب شدهی بر روی آن
در نگارشهای قبل از RTM، با فراخوانی app.UseRuntimeInfoPage در متد Configure کلاس Startup، ریز اطلاعاتی از وضعیت سرور و بستههای موجود در آن با مراجعهی به آدرس http://site/runtimeinfo نمایش داده میشدند. این مورد خاص از نگارش RTM
حذف شدهاست (احتمالا به دلایل امنیتی). البته اگر علاقمند به بررسی کدهای آن باشید، هنوز تاریخچهی آن در GitHub
موجود است .
مدیریت خطاها در برنامههای ASP.NET Core 1.0
به متد Configure کلاس Startup مراجعه کرد و یک سطر استثناء را به ابتدای کدهای Middleware انتهایی آن اضافه کنید:
public void Configure(IApplicationBuilder app)
{
app.Run(async context =>
{
throw new Exception("Generic Error");
await context.Response.WriteAsync("Hello DNT!");
});
}
هدف این است که بررسی کنیم اگر استثنایی در یک Middleware رخ داد، برنامه چه خروجی را نمایش میدهد.
در این حالت اگر برنامه را اجرا کنیم، این خروجی را دریافت خواهیم کرد:
و اگر به وضعیت بازگشت داده شدهی از طرف سرور دقت کنیم، فقط internal server error است:
در اینجا برخلاف نگارشهای قبلی ASP.NET، دیگر حتی صفحهی زرد رنگ معروف نمایش خطاها (yellow screen of death) نیز فعال نیستند. برای فعال سازی آن نیاز است Middleware مرتبط با آنرا به نحو ذیل به برنامه معرفی کنیم:
public void Configure(IApplicationBuilder app)
{
app.UseDeveloperExceptionPage();
پس از این فعال سازی، اگر مجددا برنامه را اجرا کنید، این خروجی را میتوان در مرورگر مشاهده کرد:
به دلایل امنیتی و عدم نشت اطلاعات سمت سرور و خصوصا عدم امکان دیباگ از راه دور برنامه توسط مهاجمین، این Middleware به صورت پیش فرض فعال نیست.
بنابراین این سؤال مطرح میشود که چگونه میتوان این صفحه را تنها در حین توسعهی برنامه نمایش داد؟
پاسخ آن به نحوهی طراحی متد Configure در کلاس Startup بر میگردد. این متد امضای ثابتی را ندارد. هر تعداد سرویسی را که نیاز داشتید، میتوانید به عنوان پارامتر این متد معرفی کنید و کار تزریق وابستگیها و نمونه سازی آنها، توسط امکانات توکار ASP.NET Core به صورت خودکار انجام میشود. برای مثال سرویس IApplicationBuilder، یکی از سرویسهای توکار ASP.NET Core است و برای تنظیم آن نیازی نیست تا کار خاصی را انجام دهیم. به همین جهت است که صرفا معرفی اینترفیس آن در این متد، وهلهای را از سازندهی برنامه در اختیار ما قرار میدهد. سرویسها را در مطلبی جداگانه مورد بررسی قرار خواهیم داد، اما فعلا جهت تکمیل بحث باید درنظر داشت که یکی دیگر از سرویسهای توکار ASP.NET Core، به نام IHostingEnvironment، اطلاعاتی را در مورد محیطی که برنامه را در آن اجرا میکنیم در اختیار ما قرار میدهد:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
روش معرفی آن نیز همانند روش معرفی سرویس IApplicationBuilder است و تنها کافی است به عنوان یک پارامتر جدید متد Configure معرفی شود. وهله سازی و تنظیمات آن نیز به صورت خودکار توسط ASP.NET Core انجام خواهد شد. اکنون پس از تزریق این سرویس، میتوان صفحهی نمایش جزئیات خطاها را تنها محدود به محیط توسعه کرد:
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
در مورد انواع محیطهای توسعه، در مطلب «
ارتقاء به ASP.NET Core 1.0 - قسمت 2 - بررسی ساختار جدید Solution» در انتهای بحث به «نقش فایل launchsetting.json» اشاره شد. اگر بر روی پروژه کلیک راست کرده و به صفحهی properties آن مراجعه کنید و یا دوبار کلیک بر روی گره properties، یک چنین تنظیمی را میتوان مشاهده کرد:
این متغیر محیطی میتواند سه مقدار Development, Staging و Production را داشته باشد و بر اساس این متغیر و مقدار آن است که یکی از سه متد ذیل مفهوم پیدا میکنند و true یا false را باز میگردانند:
if(env.IsDevelopment()){ }
if(env.IsProduction()){ }
if(env.IsStaging()){ }
نمایش و مدیریت خطاها در حالت Production
از app.UseDeveloperExceptionPage صرفا در حالت توسعه استفاده کنید؛ چون اطلاعات نمایش داده شدهی توسط آن، بیش از اندازه برای مهاجمین مفید است. اما در حالت توزیع نهایی بر روی سرور چه باید کرد؟
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(errorHandlingPath: "/MyControllerName/SomeActionMethodName");
}
در این حالت از Middleware دیگری به نام ExceptionHandler با فراخوانی app.UseExceptionHandler میتوان کمک گرفت. کار آن هدایت کاربر به صفحهای خاص از برنامه، در صورت بروز استثنایی است. در اینجا شما میتوانید یک صفحهی عمومی «خطایی رخ دادهاست» را بدون ذکر هیچ نوع جزئیاتی، به کاربر نمایش دهید.
به علاوه در اینجا (در این قسمت خاص برنامه که توسط پارامتر errorHandlingPath مشخص شدهاست) با استفاده از قطعه کد ذیل، دسترسی کاملی را به اطلاعات خطای رخ داده، جهت ثبت و لاگ آن دارید:
var feature = HttpContext.Features.Get<IExceptionHandlerFeature>();
var error = feature?.Error;
بررسی میانافزار StatusCode
این میان افزار برای مدیریت responseهایی که status code آنها بین 400 تا 600 هستند، طراحی شدهاست. بر اساس این شمارهها، میتوان خطای خاصی را بازگشت داده و یا کاربر را به یک صفحه یا کنترلر خاصی در برنامه، هدایت کرد.
در حالت عادی ثبت آن
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseStatusCodePages();
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler(errorHandlingPath: "/MyControllerName/SomeActionMethodName");
}
}
تنها یک خروجی متنی را نمایش میدهد.
برای نمونه در اینجا مسیری درخواست داده شدهاست که توسط برنامه پردازش نمیشود و وجود ندارد.
اگر خواستید تا status code واقعی، به کاربر بازگشت داده شود، اما خروجی نمایش داده شده را سفارشی سازی کنید، میتوانید از متد UseStatusCodePagesWithReExecute استفاده نمائید:
app.UseStatusCodePagesWithReExecute("/MyControllerName/SomeActionMethodName/{0}");
در اینجا کاربر هنوز status code مساوی 404 را دریافت میکند (مناسب برای موتورهای جستجو)، اما اکشن متد خاصی در برنامه، سبب بازگشت یک View سفارشی به کاربر خواهد شد (بجای نمایش یک متن ساده). پارامتر {0} آن نیز همان شماره status code بازگشتی است.