Search code examples
asp.netasp.net-corefluentvalidation

FluentValidation ASP.NET Core. Can't to validate IFormFile


I have a model

[AutoMap(typeof(WorkDTO), ReverseMap = true)]
public class WorkDTO
{
  public Guid Id { get; set; }
  public string UserId { get; set; }
  public string Name { get; set; }
  public string AvaUrl { get; set; }
  public List<IFormFile> AvaWork { get; set; }
}

I have FluentValidator which is configured for this model.

public WorkDtoValidator()
{
    RuleFor(p => p.Name)
        .NotNull()
        .NotEmpty()
        .Length(2, 50)
        .WithMessage("{PropertyName} should be not empty.");
    RuleFor(p => p.Description)
        .NotNull()
        .NotEmpty()
        .Length(50, 1000)
        .WithMessage("{PropertyName} should be not empty.");
    RuleFor(x => x.AvaWork).NotEmpty();
}

And configured it in StartUp

services.AddControllers()
            .AddFluentValidation();
services.AddSingleton<IValidator<WorkDTO>, WorkDtoValidator>();

Validation work normal, but if I don`t send property AvaWork. If in model comes AvaWork than I get an exception

enter image description here

I tried without RuleFor(x => x.AvaWork).NotEmpty(); The same result. I Have a special validation class for validation AvaWork.

public class FileValidator : AbstractValidator<IFormFile>
{
    public FileValidator()
    {
        RuleFor(x => x.Length).NotNull().LessThanOrEqualTo(100)
            .WithMessage("File size is larger than allowed");

        RuleFor(x => x.ContentType).NotNull().Must(x => x.Equals("image/jpeg") || 
        x.Equals("image/jpg") || x.Equals("image/png"))
            .WithMessage("File type is larger than allowed");
    }
}

And added this line RuleForEach(x => x.AvaWork ).SetValidator(new FileValidator()); The same result.

If in controller will be only List<IFormFile> AvaWork (not model public async Task<IActionResult> CreateWork(WorkDTO model)) It works good.

I don`t have any ideas.


Solution

  • The problem was in both sides. In front(Angular 11 - Typescript) I need add all properties to formData. By this way

    const formData = new FormData();
    formData.append('Name', this.createWorkForm.get('Name').value);
    formData.append('Description', this.createWorkForm.get('description').value);
    
    
    this.WorkMarkets.forEach(market => {
      formData.append('Markets', market);
    });
    
    this.WorkingHours.forEach(session => {
      formData.append('WorkingHours', session);
    });
    
    if (this.fileToUploadMain != null) {
      formData.append('AvaWork', this.fileToUploadMain, this.fileToUploadMain.name);
    }
    
    this.apiWorkService.createWork(formData).subscribe(
      suc => {
        console.log(suc);
      },
      err => {
        console.log(err);
      });
    

    And in back side add [FromForm] in Controller param

    public async Task<IActionResult> CreateWork([FromForm]WorkDTO formWork)
    

    Model of WorkDTO

    public class WorkDTO
    {
        public Guid Id { get; set; }
        public string UserId { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
        public IEnumerable<string> WorkingHours { get; set; }
        public IEnumerable<string> Markets { get; set; }
        public string AvaUrl { get; set; }
        public IFormFile AvaWork { get; set; }
    }