devnotcom / devnot-mentor-back-end

Devnot Mentor projesinin Back-end ve Rest API kaynak kodlarını içermektedir.
MIT License
69 stars 21 forks source link

ApiController attribute'nun model validation için sundukları #32

Closed halilkocaoz closed 3 years ago

halilkocaoz commented 3 years ago

Merhaba, .NET 5 ile model validation için şimdilik herhangi bir action filter veya farklı bir middleware yazmamıza gerek yok diye düşünüyorum. ValidateModelStateAttribute.cs'ı kaldırarak, sadece request yaparken kullanılan data transfer objelerinin gereksinimlerini belirmemiz, otomatik olarak kontrol edilmesini sağlar.

Küçük bir örnek ile ApiController attribute eklediğimiz zaman model validation ile ilgili bize neler sunduğunu görelim,

[ApiController]
[Route("[controller]")]
public class ExampleController : ControllerBase
{
    public class ExampleRequestDTO
    {
        [Required(ErrorMessage = "Custom error message")]
        public string Name { get; set; }

        //
        public string Phone { get; set; }

        [Range(18, int.MaxValue)]
        public int Age { get; set; }
    }

    [HttpPost]
    public IActionResult Post([FromBody] ExampleRequestDTO model)
    {
        return null;
    }
}

Request body:

{
  "name": "",
  "phone": "",
  "age": 0
}

Http response status code 400 ile birlikte response body:

{
  "type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
  "title": "One or more validation errors occurred.",
  "status": 400,
  "traceId": "00-27df2e0524036841b4277c93b20d7893-1de35f725998f444-00",
  "errors": {
    "Age": [
      "The field Age must be between 18 and 2147483647."
    ],
    "Name": [
      "Custom error message"
    ]
  }
}

Bu konuyla alakalı çok uzun bir dokümantasyon var, detayları için isterseniz bunu inceleyebilirsiniz.

yusufyilmazfr commented 3 years ago

Bu işlem .NET 5 öncesinde de var, bizim orada custom bir attribute yazma amacımız model valid olmadığı durumda anlamlı bir response vermekti.

public class ValidateModelStateAttribute : ActionFilterAttribute
{

    public override void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            context.Result = new BadRequestObjectResult(new ErrorApiResponse(ResultMessage.InvalidModel));
        }
    }
}
halilkocaoz commented 3 years ago

Evet. ApiController attribute'u .NET Core'un çok daha erken safhalarında geldi. Model validation ise, sanırım daha sonraki release bir versiyonda eklendi diye hatırlıyorum. Fakat şuanda bütün .NET Core tabanlı projelerde kullanılabilir.

yazdığımız action filter ile model valid olmadığında aldığımız response

{
  "success": false,
  "message": "messages.error.general.invalidModel"
}

Sadece ApiController'ı kullanırsak daha anlaşılır bir response dönebiliriz diye düşündüm.