Validating data in the service layer against DTOs,

2019-05-25 01:15发布

问题:

I'm working on an ASP.NET MVC project. In the project I have a service layer that accepts DTOs for CRUD operations. When I need to validate business logic, should the validator accept DTOs, Entity Models, or something else entirely?

For example:

public class ProductService: IProductService
{
    public ValidationResult CreateProduct(ProductDTO productDto)
    {
       //call productValidator.Validate(productDto) on the DTO here?

        Product productEntityModel = mapper.Map<Product>(productDto);

        //or, call productValidator.Validate(productEntityModel) on the Entity model here?

        if(validationResult.Valid)
        {
            _dbContext.Products.Add(productEntityModel);
            _dbContext.SaveChanges();
        }

        return validationResult
    }
}

Some thoughts:

  • I've seen online some talk of creating a POCO which can have validation logic (rather than using a validation service) and even other business logic inside of it. This makes sense, but it is yet one more "representaion" of a product that has to be managed and maintained.
  • Validating against the DTO maybe seems a little more reasonable since that is that the caller is sending to the service?

Thanks for the help!!

回答1:

When I need to validate business logic, should the validator accept DTOs, Entity Models, or something else entirely?

Normally, we perform validation in ViewModel class using DataAnnotations, so that we can return user friendly ModelError. For example,

public class LoginViewModel
{
   [Display(Name = "Username")]
   [Required(ErrorMessage = "Please enter your username.")]
   public string UserName { get; set; }
}

public async Task<ActionResult> Login(LoginModel model, string returnUrl)
{
   if (ModelState.IsValid)
   {
      ...
      ModelState.AddModelError("", "User is not authorized!");
   }
   ...
}

Although you can validate some business logic inside ProductService, you cannot return MVC ModelError, since Service/Repository Layer should not depends on ASP.NET MVC (or any UI components).

Most of the error inside Service/Repository Layer are unexpected error instead of user error. We norammly log those error in NLog or Log4Net, and redirect user to custom error page.