برنامه نویسی

10 روش بدی که باید در کنترلرهای ASP.NET Core API اجتناب کنید

هنگام توسعه کنترل‌کننده‌ها در ASP.NET Core، اقدامات خاصی وجود دارد که باید از آنها اجتناب کرد تا از قابلیت نگهداری، عملکرد و پایبندی به بهترین شیوه‌ها اطمینان حاصل شود. در اینجا 10 چیزی وجود دارد که باید در کنترلرهای خود از آنها اجتناب کنیم.


1. کوپلینگ محکم

از اتصال محکم در کنترلرهایی با وابستگی ها یا چارچوب های خاص خودداری کنید. در عوض، از تزریق وابستگی برای تزریق وابستگی ها به کنترلرها استفاده کنید. این باعث تقویت اتصال شل می شود و کد را قابل آزمایش تر و قابل نگهداری تر می کند.

// Avoid:
[ApiController]
[Route("[controller]")]
public class ProductController : ControllerBase
{
    ProductService productService = new ProductService();
    // ...
}


// Prefer:
[ApiController]
[Route("[controller]")]
public class ProductController : ControllerBase
{
    private readonly ILogger<ProductController> _logger;
    private readonly IProductService _productService;

    public ProductController(IProductService productService, ILogger<ProductController> logger)
    {
        _logger = logger;
        _productService = productService;
    }
    // ...
}
وارد حالت تمام صفحه شوید

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

درباره تزریق وابستگی بیشتر بدانید

2. اختلاط نگرانی ها

کنترل‌کننده‌ها باید روی رسیدگی به درخواست‌های HTTP و تولید پاسخ‌ها تمرکز کنند. از اختلاط نگرانی هایی مانند دسترسی به داده ها، احراز هویت یا مجوز مستقیماً در کنترلر خودداری کنید. این مسئولیت‌ها را به کلاس‌های جداگانه یا میان‌افزار محول کنید.

// Avoid:
[HttpPost]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    // Authentication and authorization logic here
    // ...
    // Data access logic here
    // ...
    return Ok(StatusCodes.Status201Created);
}


// Prefer:
[HttpPost]
[Authorize]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    await _productService.CreateAsync(productDto);

    return Ok(StatusCodes.Status201Created);
}
وارد حالت تمام صفحه شوید

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

درباره اصل مسئولیت واحد بیشتر بدانید | تفکیک نگرانی ها

3. عدم رسیدگی به استثنا

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

// Avoid: (Inconsistent error handling or try catch everywhere)
[HttpPost]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    try
    {
        await _productService.CreateAsync(productDto);

        return Ok(StatusCodes.Status201Created);
    }
    catch (ProductValidationException ex)
    {
        return BadRequest(ex.Message);
    }
    catch (Exception ex)
    {
        _logger.LogError(ex, "An error occurred while creating the product.");
        return StatusCode(StatusCodes.Status500InternalServerError);
    }
}


// Prefer: Exception filters or Middleware
[HttpPost]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    await _productService.CreateAsync(productDto);

    return Ok(StatusCodes.Status201Created);
}
وارد حالت تمام صفحه شوید

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

به عنوان مثال یک میان افزار استثنای جهانی

public class ExceptionMiddleware
{
    private readonly RequestDelegate _next;

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

    public async Task InvokeAsync(HttpContext context)
    {
        try
        {
            await _next(context);
        }
        catch (Exception ex)
        {
            // Log the error
            // ...

            await HandleExceptionAsync(context, ex);
        }
    }

    private Task HandleExceptionAsync(HttpContext context, Exception exception)
    {
        context.Response.ContentType = "application/json";
        context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;

        var response = new
        {
            StatusCode = context.Response.StatusCode,
            Message = "Internal Server Error"
        };

        return context.Response.WriteAsync(JsonConvert.SerializeObject(response));
    }
}
وارد حالت تمام صفحه شوید

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

با استفاده از این میان‌افزار استثنایی، هر استثنای غیرقابل کنترلی که در طول پردازش درخواست HTTP رخ می‌دهد، شناسایی می‌شود و یک پاسخ JSON با یک پیام خطای عمومی و کد وضعیت 500 (خطای سرور داخلی) به مشتری بازگردانده می‌شود.

ما می‌توانیم روش HandleExceptionAsync را سفارشی کنیم تا اطلاعات خطای دقیق‌تری را شامل شود یا ساختار پاسخ را مطابق با نیاز خود اصلاح کنیم.

برای استفاده از این میان افزار در برنامه ASP.NET Core Web API، می توانیم کد زیر را به برنامه خود اضافه کنیم Startup.cs فایل یا Program.cs نت 6.

app.UseMiddleware<ExceptionMiddleware>();
وارد حالت تمام صفحه شوید

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

درباره فیلترهای استثنا بیشتر بدانید | میان افزار

4. عملیات طولانی مدت

از انجام عملیات طولانی مدت به صورت همزمان در کنترلرها خودداری کنید. چنین وظایفی را به کارگران پس‌زمینه بارگذاری کنید یا از برنامه‌نویسی ناهمزمان استفاده کنید.

// Avoid:
[HttpGet]
public IActionResult GenerateReport()
{
    // Long-running operation
    // ...
    return Ok(report);
}


// Prefer:
[HttpGet]
public async Task<IActionResult> GenerateReport()
{
    // Offload the long-running operation to a background worker
    await _reportGenerationService.GenerateAsync();
    return Ok();
}
وارد حالت تمام صفحه شوید

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

درباره کارهای پس زمینه بیشتر بیاموزید | زمانبندی آتش سوزی | کار ناهمزمان

5. عدم اعتبار سنجی

اعتبار سنجی ورودی برای اطمینان از یکپارچگی و امنیت برنامه بسیار مهم است. از عدم توجه به اعتبارسنجی ورودی در کنترلرهای خود اجتناب کنید. ویژگی های اعتبارسنجی مدل اهرمی، مانند [Required]، [MaxLength]و منطق اعتبارسنجی سفارشی برای اعتبارسنجی داده های دریافتی.

// Avoid:
[HttpPost]
public async Task<IActionResult> CreateProduct(ProductDto productDto)
{
    // No validation
    await _productService.CreateAsync(productDto);
    return Ok(StatusCodes.Status201Created);
}


// Prefer:
[HttpPost]
public async Task<IActionResult> CreateProduct([FromBody] ProductDto productDto)
{
    if (!ModelState.IsValid)
    {
        return StatusCode(StatusCodes.Status400BadRequest, ModelState);                
    }

    await _productService.CreateAsync(productDto);
    return Ok(StatusCodes.Status201Created);
}
وارد حالت تمام صفحه شوید

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

درباره اعتبارسنجی مدل بیشتر بدانید | Fluent Validation

6. دسترسی مستقیم به پایگاه داده

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

// Avoid:
[HttpGet]
public IActionResult GetProduct(int productId)
{
    var product = dbContext.Products.Find(productId);
    return Ok(product);
}


// Prefer:
[HttpGet]
public async Task<IActionResult> GetProduct(int productId)
{
    var product = await _productService.GetByIdAsync(productId);
    return Ok(product);
}
وارد حالت تمام صفحه شوید

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

درباره الگوی مخزن یا لایه داده بیشتر بدانید

7. عدم وجود کش

در صورت لزوم از استفاده نکردن از مکانیسم های کش خودداری کنید. از کش برای بهبود عملکرد و کاهش بار روی سرور استفاده کنید.

// Avoid:
[HttpGet]
public async Task<IActionResult> GetProducts()
{
    var products = await _productService.GetAllAsync();
    return Ok(products);
}


// Prefer:
[HttpGet]
[ResponseCache(Duration = 60)] // Cache the response for 60 seconds
public async Task<IActionResult> GetProducts()
{
    var products = await _productService.GetAllAsync();
    return Ok(products);
}
وارد حالت تمام صفحه شوید

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

درباره Caching بیشتر بدانید | ذخیره پاسخ

8. عدم احراز هویت و مجوز

از اجرای نکردن احراز هویت و مجوز برای عملیات حساس خودداری کنید. بر این اساس کنترلرها را ایمن کنید.

// Avoid:
[HttpPost]
public async Task<IActionResult> DeleteProduct(int productId)
{
    // No authentication or authorization
    await _productService.DeleteAsync(productId);
    return StatusCode(StatusCodes.Status200OK);
}


// Prefer:
[HttpPost]
[Authorize(Roles = "Admin")]
public async Task<IActionResult> DeleteProduct(int productId)
{
    await _productService.DeleteAsync(productId);
    return StatusCode(StatusCodes.Status200OK);
}
وارد حالت تمام صفحه شوید

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

درباره احراز هویت و مجوز بیشتر بیاموزید

9. منطق بیش از حد

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

// Avoid:
[HttpGet]
public async Task<IActionResult> GetProducts()
{
    // Complex business logic here
    // ...
    // ...
    // ...

    return Ok(products);
}


// Prefer:
[HttpGet]
public async Task<IActionResult> GetProducts()
{
    var products = await _productService.GetAllAsync();
    return Ok(products);
}
وارد حالت تمام صفحه شوید

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

درباره معماری های رایج برنامه های وب بیشتر بیاموزید

10. نادیده گرفتن افعال HTTP و اصول RESTful

کنترلرها در ASP.NET Core باید اصول معماری RESTful را رعایت کنند. از استفاده از افعال یا اقدامات نامناسب HTTP که با قراردادهای RESTful همخوانی ندارند، خودداری کنید. از افعال مناسب HTTP (GET، POST، PUT، DELETE و غیره) برای انجام عملیات مربوطه بر روی منابع استفاده کنید.

// Avoid:
public IActionResult DeleteProduct(int id)
{
    // ...
}


// Prefer:
[HttpDelete("/api/products/{id}")]
[ProducesResponseType(StatusCodes.Status200OK)]
[Authorize]
public IActionResult DeleteProduct(int id)
{
    // ...
}
وارد حالت تمام صفحه شوید

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

درباره طراحی RESTful web API بیشتر بیاموزید


با اجتناب از این مشکلات رایج، می‌توانیم کنترل‌کننده‌هایی را در ASP.NET Core توسعه دهیم که قابل نگهداری، آزمایش‌پذیر بوده و بهترین روش‌ها را برای توسعه وب API دنبال کنند.


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

از طریق مقالاتم، نکات و تجربیات مربوط به توسعه وب، شغل و آخرین روندهای فناوری را به اشتراک می گذارم. با من همراه باشید تا با هم این موضوعات هیجان انگیز را بررسی کنیم. بیایید با هم یاد بگیریم، رشد کنیم و خلق کنیم!

➕مقاله بیشتر در مورد برنامه نویسی، مشاغل و گرایش های فناوری.

🔔 من را در مدیوم دنبال کنید | توییتر

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

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

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

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