برنامه نویسی

میان افزار گاردین: مدیریت خطاها در سطح جهانی در ASP.NET

Summarize this content to 400 words in Persian Lang

سلام وجود دارد! 👋🏻

در چند مقاله گذشته، من در مورد مفاهیم خالص C# صحبت کرده ام، چیزهایی مانند نمایندگان، توکن های لغو، IQueryable و غیره در این مقاله، ما بر روی چیزی خاص تمرکز می کنیم، که این است رسیدگی به استثنا، اما در مقیاس جهانی از طریق استفاده از اجزای میان افزاری که در پروژه های ASP داریم. اگر جالب به نظر می رسد، دست و پنجه نرم کنید و اجازه دهید نمایش را ادامه دهیم!

رسیدگی به استثناء به طور کلی

استفاده از استثناها در برنامه‌های ما یک مکانیسم کلی است و برای موارد استفاده مختلف استفاده می‌شود و همیشه به روش‌های مختلف مورد استفاده قرار می‌گیرد. در برخی از پایگاه های کد، از استثناهایی برای کنترل جریان استفاده می کنید، مانند این مورد:

public async Task<UserManagerResponse> RegisterUserAsync(RegisterRequest request)
{
var existingUser = await _userManager.FindByEmailAsync(request.Email!);

if (existingUser is not null)
throw new UserCreationFailedException(message: “Email is taken”);
// code removed for brevity…
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مثال قبلی، یک استثنا سفارشی برای کنترل جریان پرتاب شده است (کاربری که قبلاً با ایمیل ارائه شده ثبت نام کرده است)، این رویکرد گاهی اوقات به عنوان جریان کنترل مبتنی بر استثنا. دیگران ممکن است از چیز دیگری مانند استفاده کنند نتیجه الگویی برای محدود کردن استفاده از استثناها در پایه کد، زیرا پرتاب و رسیدگی به استثناها پرهزینه است، زیرا آنها علاوه بر تخصیص کد، باید پشته فراخوانی را منتشر کنند و در جای دیگری در کد مدیریت شوند. Exception شی اگر به تجزیه و تحلیل عمیق تر علاقه مند هستید، این مقاله را بررسی کنید:تجزیه و تحلیل عملکرد استثنایی – راهنمای بازیکنان سی شارپ

چرا جهانی هندلینگ؟

با فرض اینکه ما یک پروژه Web API داریم، کدی که استثناها را ایجاد می کند باید در جایی مدیریت شود، می توانید این کار را در کنترلر انجام دهید، به عنوان مثال RegisterUser نقطه پایانی که از کد نشان داده شده قبلی استفاده می کند:

try
{
var registerResult = await _authRepository
.RegisterUserAsync(request);

if (registerResult.Succeeded)

}
catch (UserCreationFailedException ex) // exception handled here and converted into an error response
{
// sign up failed
return BadRequest(new ApiErrorResponse
{
ErrorMessage = ex.Message
});
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر از استثناها برای کنترل جریان استفاده می‌کنید، که یک سناریوی بسیار رایج در توسعه برنامه‌ها است، زیرا پیاده‌سازی روشی آسان است، و تجربه توسعه‌دهنده‌ای عالی دارد زیرا اجرای کد را ساده می‌کند (در صورتی که درست انجام شود)، شما باید تمام آن استثناها را در لایه‌ای در برنامه‌تان پیدا کنید تا آن‌ها را به پاسخ‌های خطای مناسبی تبدیل کنید که کاربران یا مصرف‌کنندگان API می‌توانند از آن استفاده کنند.

شما می توانید ببینید که این به کجا می رود، اضافه کردن try {} catch {} بلوک‌های موجود در نقاط پایانی، سرویس‌ها یا هر چیز دیگری که باشد، خوانایی کد شما را کاهش می‌دهد و نویز زیادی ایجاد می‌کند. ناگفته نماند که مسئولیت های بیشتری را به بخش هایی از کد مرتبط می کند که برای رسیدگی به استثنائات در نظر گرفته نشده اند. همانطور که کنترلر شما باید درخواستی را دریافت کند، آن را به عملکرد صحیح نگاشت کنید، که سرویس مناسب را فراخوانی می کند یا پرس و جوی مناسب را انجام می دهد و پاسخ را ارسال می کند. نباید حسابداری و رسیدگی به همه انواع استثناهایی باشد که ممکن است یک سرویس یا مخزن ایجاد کند.

در یک سطح انتزاعی تر، اگر از چیزی مانند MediatR و CQRS استفاده می کنید، نقاط پایانی کنترلر شما عمدتاً همیشه حاوی خطوط مشابهی از کد هستند، مانند این:

[HttpPost(“login”)] public async Task<IActionResult> LoginUserAsync([FromBody] RegisterRequest request, CancellationToken cancellationToken)
{
var command = new Login.Command(request);
var response = await _sender.Send(command, cancellationToken);
return Ok(new ApiResponse<LoginResponse>(response)
{
Message = “User login succeeded”,
IsSuccess = true
});
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

دستور/پرس و جو را بسازید، آن را ارسال کنید، پاسخی را برگردانید.

اما در آن صورت، چه کسی استثناهای پرتاب شده را مدیریت می کند؟ را وارد کنید میان افزار مدیریت خطای جهانی، این کاملاً یک لقمه است

میان افزار مدیریت خطای جهانی

وقتی برای اولین بار با ASP شروع می کنید، شرایط را می شنوید درخواست خط لوله و میان افزار من در مقاله قبلی در مورد خط لوله درخواست در ASP و اینکه یک میان افزار چیست صحبت کرده ام، اگر علاقه مند هستید می توانید آن را در اینجا بررسی کنید:خط لوله درخواست در ASP NET توضیح داده شد

به طور خلاصه، هر درخواستی که وارد برنامه ما می شود، باید از طریق آن خط لوله عبور کند، بنابراین ما می توانیم از آن استفاده کنیم و یک مورد واحد قرار دهیم. try {} catch {} بلوک که می‌تواند انواع استثناها را مدیریت کند و پاسخ مناسب را بر اساس نوع استثنا ایجاد می‌کند تا کنترل‌کننده‌ها، سرویس‌ها و هر چیز دیگری مجبور نباشند خود را درگیر فرآیند رسیدگی به استثناها کنند.

ایجاد یک میان افزار

ایجاد یک میان افزار در واقع بسیار ساده است، دو راه برای ایجاد آنها وجود دارد، یکی به صورت قراردادی و دیگری با پیاده سازی IMiddleware رابط و پیاده سازی آن InvokeAsync روش، ما از روش اول که به صورت قراردادی است استفاده خواهیم کرد.

من دوست دارم میان افزارهای خود را در پوشه ای به نام Middlewares نگه دارم، اما این به شما بستگی دارد که کجا کلاس را ایجاد کنید.

در اینجا کد مورد نیاز برای Middleware ما آمده است:

public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;

public ErrorHandlingMiddleware(RequestDelegate next)
{
_next = next;
}

public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(_context);
}
catch (Exception ex)
{
await HandleExceptionAsync(context, ex);
}
}

private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{

}
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

من با توضیح جریان شروع می کنم و سپس اجرای آن را شروع می کنم HandleExceptionAsync روش

از آنجایی که هر درخواستی از طریق این میان‌افزار ارسال می‌شود، در هر نقطه از برنامه، زمانی که یک استثنا پرتاب می‌شود، اینجا جایی است که گرفته می‌شود و رسیدگی می‌شود. این امر منطق رسیدگی به استثناها را متمرکزتر می کند زیرا اکنون استثناهایی که به تجربه کاربر مربوط می شوند در این مکان واحد رسیدگی می شوند. مانند این میان‌افزار استثناهایی را که به کاربر علاقه مند هستند را می‌گیرد، یک پاسخ خطای معنی‌دار از آن‌ها ایجاد می‌کند و آن را در پاسخ ارسال می‌کند.

پیاده سازی منطق رسیدگی به خطا

همه استثناها از Exception کلاس پایه، بنابراین استثنایی که می‌گیریم، می‌تواند به هر استثنای سفارشی ارسال شود، بنابراین در HandleExceptionAsync روش، می توانیم موارد زیر را انجام دهیم:

private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
HttpStatusCode code = HttpStatusCode.InternalServerError;
string errorMessage = string.Empty;

// Handle the different exception types here
switch(Exception)
{
case AuthenticationFailedException ex:
code = HttpStatusCode.BadRequest;
errorMessage = ex.Message;
break;
case NotAuthorizedException ex:
code = HttpStatusCode.Unauthorized;
errorMessage = ex.Message;
break;
case OperationFailedException ex:
code = HttpStatusCode.BadRequest;
errorMessage = ex.Message;
break;
case Exception ex:
code = HttpStatusCode.InternalServerError;
errorMessage = “Something went wrong. Please try again”;
break;
}

context.Response.ContentType = “application/json”;
context.Response.StatusCode = (int)code;
var errorResponse = new ApiErrorResponse(code, errorMessage);
var serializedErrorResponse = JsonSerializer.Serialize(errorResponse);

await context.Response.WriteAsync(serializedErrorResponse);
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نوع با نام ApiErrorResponse یک کلاس ساده با دو ویژگی است که پیام خطا و کد وضعیت HTTP را محصور می کند و دارای اعلان زیر است:

public class ApiErrorResponse
{
public string? ErrorMessage { get; set; }

public int StatusCode { get; set; }

public ApiErrorResponse(string errorMessage)
{
ErrorMessage = errorMessage;
}

public ApiErrorResponse(string errorMessage, int statusCode)
{
ErrorMessage = errorMessage;
StatusCode = statusCode;
}
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد در این روش تنها یک کار را انجام می دهد، به نوع استثنا نگاه می کند و کد وضعیت پاسخ و محتوای آن را بر روی اطلاعات استخراج شده از استثنا تنظیم می کند.

وقتی نوع جدیدی از استثنا را معرفی می کنید، فقط می توانید a اضافه کنید case برای آن در switch بلاک کنید، و میان‌افزار می‌تواند این نوع استثنا را نیز مدیریت کند، بنابراین تنها کاری که باید انجام دهید این است که استثنای جدید خود را ایجاد کنید، شروع کنید به پرتاب آن در هر کجا که نیاز دارید، و فقط یک مورد برای آن در میان‌افزار اضافه کنید، و این کار را انجام می‌دهد. بتوانید از تبدیل آن به چیزی که می توانید برای کاربران یا مصرف کنندگان API خود ارسال کنید مراقبت کنید.

مزیت اضافی

یکی دیگر از مزایای این رویکرد، این است که به دلیل اینکه مکان مرکزی مربوط به رسیدگی به استثناها است، می‌توانید ادامه دهید و یک نمونه لاگر تزریق کنید، و همچنین ثبت استثناها را در همان میان افزار متمرکز کنید:

public class ErrorHandlingMiddleware
{
private readonly RequestDelegate _next;
private readonly ILogger<ErrorHandlingMiddleware> _logger;

public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
{
_next = next;
_logger = logger;
}

public async Task InvokeAsync(HttpContext context)
{
try
{
await _next(_context);
}
catch (Exception ex)
{
await HandleExceptionAsync();
_logger.LogError(ex);
}
}

}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در نهایت، اکنون که میان افزار ما در جای خود قرار دارد، باید جلو برویم و آن را به خط لوله درخواست اضافه کنیم. در Program.cs، این خط را اضافه کنید:

app.UseMiddleware<ErrorHandlingMiddleware>();

if (app.Environment.IsDevelopment())
{
app.UseSwagger();
app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

💡 توجه: ثبت کردن خطای مدیریت میان‌افزار ابتدا در خط لوله بسیار مهم است، زیرا این امر به آن اجازه می‌دهد تا استثناهایی را که در مؤلفه‌های میان‌افزار بعدی در زنجیره ایجاد می‌شوند مدیریت کند، و بنابراین می‌تواند در نهایت با هر استثنایی که برنامه ما قرار است ایجاد کند، مقابله کند. این استثنا در طول پردازش یک درخواست دریافتی رخ داده است.

نتیجه گیری

اوه! تا آخرش رسیدیم! ما مکانیسم مدیریت خطای جهانی را بررسی، بحث و اجرا کردیم! کمان بگیر!پست بسیار طولانی بود، اما ما به چیزهای زیادی نگاه کرده ایم، از درک هدف مدیریت استثنا در سطح جهانی، ایجاد میان افزار، و دیدن نحوه رسیدگی به استثناها. اکنون برای هر سناریویی که می‌خواهید با استثناها در سطح جهانی و متمرکزتر مقابله کنید، می‌توانید از این رویکرد استفاده کنید و آن را متناسب با نیازهای خود تنظیم کنید!

با تشکر برای خواندن!

سلام وجود دارد! 👋🏻

در چند مقاله گذشته، من در مورد مفاهیم خالص C# صحبت کرده ام، چیزهایی مانند نمایندگان، توکن های لغو، IQueryable و غیره در این مقاله، ما بر روی چیزی خاص تمرکز می کنیم، که این است رسیدگی به استثنا، اما در مقیاس جهانی از طریق استفاده از اجزای میان افزاری که در پروژه های ASP داریم. اگر جالب به نظر می رسد، دست و پنجه نرم کنید و اجازه دهید نمایش را ادامه دهیم!

رسیدگی به استثناء به طور کلی

استفاده از استثناها در برنامه‌های ما یک مکانیسم کلی است و برای موارد استفاده مختلف استفاده می‌شود و همیشه به روش‌های مختلف مورد استفاده قرار می‌گیرد. در برخی از پایگاه های کد، از استثناهایی برای کنترل جریان استفاده می کنید، مانند این مورد:


public async Task<UserManagerResponse> RegisterUserAsync(RegisterRequest request)
{
    var existingUser = await _userManager.FindByEmailAsync(request.Email!);

    if (existingUser is not null)
        throw new UserCreationFailedException(message: "Email is taken");
    // code removed for brevity...
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در مثال قبلی، یک استثنا سفارشی برای کنترل جریان پرتاب شده است (کاربری که قبلاً با ایمیل ارائه شده ثبت نام کرده است)، این رویکرد گاهی اوقات به عنوان جریان کنترل مبتنی بر استثنا. دیگران ممکن است از چیز دیگری مانند استفاده کنند نتیجه الگویی برای محدود کردن استفاده از استثناها در پایه کد، زیرا پرتاب و رسیدگی به استثناها پرهزینه است، زیرا آنها علاوه بر تخصیص کد، باید پشته فراخوانی را منتشر کنند و در جای دیگری در کد مدیریت شوند. Exception شی اگر به تجزیه و تحلیل عمیق تر علاقه مند هستید، این مقاله را بررسی کنید:
تجزیه و تحلیل عملکرد استثنایی – راهنمای بازیکنان سی شارپ

چرا جهانی هندلینگ؟

با فرض اینکه ما یک پروژه Web API داریم، کدی که استثناها را ایجاد می کند باید در جایی مدیریت شود، می توانید این کار را در کنترلر انجام دهید، به عنوان مثال RegisterUser نقطه پایانی که از کد نشان داده شده قبلی استفاده می کند:


try
{
    var registerResult = await _authRepository
                               .RegisterUserAsync(request);

    if (registerResult.Succeeded)
      ...
}
catch (UserCreationFailedException ex) // exception handled here and converted into an error response
{
    // sign up failed
    return BadRequest(new ApiErrorResponse
    {
        ErrorMessage = ex.Message
    });
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

اگر از استثناها برای کنترل جریان استفاده می‌کنید، که یک سناریوی بسیار رایج در توسعه برنامه‌ها است، زیرا پیاده‌سازی روشی آسان است، و تجربه توسعه‌دهنده‌ای عالی دارد زیرا اجرای کد را ساده می‌کند (در صورتی که درست انجام شود)، شما باید تمام آن استثناها را در لایه‌ای در برنامه‌تان پیدا کنید تا آن‌ها را به پاسخ‌های خطای مناسبی تبدیل کنید که کاربران یا مصرف‌کنندگان API می‌توانند از آن استفاده کنند.

شما می توانید ببینید که این به کجا می رود، اضافه کردن try {} catch {} بلوک‌های موجود در نقاط پایانی، سرویس‌ها یا هر چیز دیگری که باشد، خوانایی کد شما را کاهش می‌دهد و نویز زیادی ایجاد می‌کند. ناگفته نماند که مسئولیت های بیشتری را به بخش هایی از کد مرتبط می کند که برای رسیدگی به استثنائات در نظر گرفته نشده اند. همانطور که کنترلر شما باید درخواستی را دریافت کند، آن را به عملکرد صحیح نگاشت کنید، که سرویس مناسب را فراخوانی می کند یا پرس و جوی مناسب را انجام می دهد و پاسخ را ارسال می کند. نباید حسابداری و رسیدگی به همه انواع استثناهایی باشد که ممکن است یک سرویس یا مخزن ایجاد کند.

در یک سطح انتزاعی تر، اگر از چیزی مانند MediatR و CQRS استفاده می کنید، نقاط پایانی کنترلر شما عمدتاً همیشه حاوی خطوط مشابهی از کد هستند، مانند این:


[HttpPost("login")]
public async Task<IActionResult> LoginUserAsync([FromBody] RegisterRequest request, CancellationToken cancellationToken)
{
    var command = new Login.Command(request);
    var response = await _sender.Send(command, cancellationToken);
    return Ok(new ApiResponse<LoginResponse>(response)
    {
        Message = "User login succeeded",
        IsSuccess = true
    });
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

دستور/پرس و جو را بسازید، آن را ارسال کنید، پاسخی را برگردانید.

اما در آن صورت، چه کسی استثناهای پرتاب شده را مدیریت می کند؟ را وارد کنید میان افزار مدیریت خطای جهانی، این کاملاً یک لقمه است

میان افزار مدیریت خطای جهانی

وقتی برای اولین بار با ASP شروع می کنید، شرایط را می شنوید درخواست خط لوله و میان افزار من در مقاله قبلی در مورد خط لوله درخواست در ASP و اینکه یک میان افزار چیست صحبت کرده ام، اگر علاقه مند هستید می توانید آن را در اینجا بررسی کنید:
خط لوله درخواست در ASP NET توضیح داده شد

به طور خلاصه، هر درخواستی که وارد برنامه ما می شود، باید از طریق آن خط لوله عبور کند، بنابراین ما می توانیم از آن استفاده کنیم و یک مورد واحد قرار دهیم. try {} catch {} بلوک که می‌تواند انواع استثناها را مدیریت کند و پاسخ مناسب را بر اساس نوع استثنا ایجاد می‌کند تا کنترل‌کننده‌ها، سرویس‌ها و هر چیز دیگری مجبور نباشند خود را درگیر فرآیند رسیدگی به استثناها کنند.

ایجاد یک میان افزار

ایجاد یک میان افزار در واقع بسیار ساده است، دو راه برای ایجاد آنها وجود دارد، یکی به صورت قراردادی و دیگری با پیاده سازی IMiddleware رابط و پیاده سازی آن InvokeAsync روش، ما از روش اول که به صورت قراردادی است استفاده خواهیم کرد.

من دوست دارم میان افزارهای خود را در پوشه ای به نام Middlewares نگه دارم، اما این به شما بستگی دارد که کجا کلاس را ایجاد کنید.

در اینجا کد مورد نیاز برای Middleware ما آمده است:


public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate _next;

    public ErrorHandlingMiddleware(RequestDelegate next)
    {
        _next = next;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(_context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync(context, ex);
        }
    }

    private async Task HandleExceptionAsync(HttpContext context, Exception exception)
    {

    }
}


وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

من با توضیح جریان شروع می کنم و سپس اجرای آن را شروع می کنم HandleExceptionAsync روش

از آنجایی که هر درخواستی از طریق این میان‌افزار ارسال می‌شود، در هر نقطه از برنامه، زمانی که یک استثنا پرتاب می‌شود، اینجا جایی است که گرفته می‌شود و رسیدگی می‌شود. این امر منطق رسیدگی به استثناها را متمرکزتر می کند زیرا اکنون استثناهایی که به تجربه کاربر مربوط می شوند در این مکان واحد رسیدگی می شوند. مانند این میان‌افزار استثناهایی را که به کاربر علاقه مند هستند را می‌گیرد، یک پاسخ خطای معنی‌دار از آن‌ها ایجاد می‌کند و آن را در پاسخ ارسال می‌کند.

پیاده سازی منطق رسیدگی به خطا

همه استثناها از Exception کلاس پایه، بنابراین استثنایی که می‌گیریم، می‌تواند به هر استثنای سفارشی ارسال شود، بنابراین در HandleExceptionAsync روش، می توانیم موارد زیر را انجام دهیم:


private async Task HandleExceptionAsync(HttpContext context, Exception exception)
{
    HttpStatusCode code = HttpStatusCode.InternalServerError;
    string errorMessage = string.Empty;

    // Handle the different exception types here
    switch(Exception)
    {
        case AuthenticationFailedException ex:
            code = HttpStatusCode.BadRequest;
            errorMessage = ex.Message;
            break;
        case NotAuthorizedException ex:
            code = HttpStatusCode.Unauthorized;
            errorMessage = ex.Message;
            break;
        case OperationFailedException ex:
            code = HttpStatusCode.BadRequest;
            errorMessage = ex.Message;
            break;
        case Exception ex:
            code = HttpStatusCode.InternalServerError;
            errorMessage = "Something went wrong. Please try again";
            break;
    }

    context.Response.ContentType = "application/json";
    context.Response.StatusCode = (int)code;
    var errorResponse = new ApiErrorResponse(code, errorMessage);
    var serializedErrorResponse = JsonSerializer.Serialize(errorResponse);

    await context.Response.WriteAsync(serializedErrorResponse);
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

نوع با نام ApiErrorResponse یک کلاس ساده با دو ویژگی است که پیام خطا و کد وضعیت HTTP را محصور می کند و دارای اعلان زیر است:


public class ApiErrorResponse
{
    public string? ErrorMessage { get; set; }

    public int StatusCode { get; set; }

    public ApiErrorResponse(string errorMessage)
    {
        ErrorMessage = errorMessage;
    }

    public ApiErrorResponse(string errorMessage, int statusCode)
    {
        ErrorMessage = errorMessage;
        StatusCode = statusCode;
    }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

کد در این روش تنها یک کار را انجام می دهد، به نوع استثنا نگاه می کند و کد وضعیت پاسخ و محتوای آن را بر روی اطلاعات استخراج شده از استثنا تنظیم می کند.

وقتی نوع جدیدی از استثنا را معرفی می کنید، فقط می توانید a اضافه کنید case برای آن در switch بلاک کنید، و میان‌افزار می‌تواند این نوع استثنا را نیز مدیریت کند، بنابراین تنها کاری که باید انجام دهید این است که استثنای جدید خود را ایجاد کنید، شروع کنید به پرتاب آن در هر کجا که نیاز دارید، و فقط یک مورد برای آن در میان‌افزار اضافه کنید، و این کار را انجام می‌دهد. بتوانید از تبدیل آن به چیزی که می توانید برای کاربران یا مصرف کنندگان API خود ارسال کنید مراقبت کنید.

مزیت اضافی

یکی دیگر از مزایای این رویکرد، این است که به دلیل اینکه مکان مرکزی مربوط به رسیدگی به استثناها است، می‌توانید ادامه دهید و یک نمونه لاگر تزریق کنید، و همچنین ثبت استثناها را در همان میان افزار متمرکز کنید:


public class ErrorHandlingMiddleware
{
    private readonly RequestDelegate _next;
    private readonly ILogger<ErrorHandlingMiddleware> _logger;

    public ErrorHandlingMiddleware(RequestDelegate next, ILogger<ErrorHandlingMiddleware> logger)
    {
        _next = next;
        _logger = logger;
    }

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(_context);
        }
        catch (Exception ex)
        {
            await HandleExceptionAsync();
            _logger.LogError(ex);
        }
    } 
    ...
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در نهایت، اکنون که میان افزار ما در جای خود قرار دارد، باید جلو برویم و آن را به خط لوله درخواست اضافه کنیم. در Program.cs، این خط را اضافه کنید:


app.UseMiddleware<ErrorHandlingMiddleware>();

if (app.Environment.IsDevelopment())
{
    app.UseSwagger();
    app.UseSwaggerUI();
}

app.UseHttpsRedirection();

app.UseAuthentication();
app.UseAuthorization();

app.MapControllers();

app.Run();

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

💡 توجه: ثبت کردن خطای مدیریت میان‌افزار ابتدا در خط لوله بسیار مهم است، زیرا این امر به آن اجازه می‌دهد تا استثناهایی را که در مؤلفه‌های میان‌افزار بعدی در زنجیره ایجاد می‌شوند مدیریت کند، و بنابراین می‌تواند در نهایت با هر استثنایی که برنامه ما قرار است ایجاد کند، مقابله کند. این استثنا در طول پردازش یک درخواست دریافتی رخ داده است.

نتیجه گیری

اوه! تا آخرش رسیدیم! ما مکانیسم مدیریت خطای جهانی را بررسی، بحث و اجرا کردیم! کمان بگیر!
پست بسیار طولانی بود، اما ما به چیزهای زیادی نگاه کرده ایم، از درک هدف مدیریت استثنا در سطح جهانی، ایجاد میان افزار، و دیدن نحوه رسیدگی به استثناها. اکنون برای هر سناریویی که می‌خواهید با استثناها در سطح جهانی و متمرکزتر مقابله کنید، می‌توانید از این رویکرد استفاده کنید و آن را متناسب با نیازهای خود تنظیم کنید!

با تشکر برای خواندن!

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا