简体   繁体   English

为 IFormFile 实施流利验证的正确方法是什么

[英]What is a correct way to implement Fluent Validation for IFormFile

I'm struggling with implementation of validation for IFormFile.我正在努力实现 IFormFile 的验证。 I'm using FluentValidation and here is my validator for FormFile:我正在使用 FluentValidation,这是我的 FormFile 验证器:

    public class PhotoValidator : AbstractValidator<IFormFile>
    {
        private readonly PhotoSettings _settings;

        public PhotoValidator(IOptionsSnapshot<PhotoSettings> snapshot)
        {
            _settings = snapshot.Value;

            RuleFor(f => f).NotNull().WithMessage("Please Attach your photo");

            RuleFor(f => f.Length).ExclusiveBetween(0, _settings.MaxBytes)
                .WithMessage($"File length should be greater than 0 and less than {_settings.MaxBytes / 1024 / 1024} MB");

            RuleFor(f => f.FileName).Must(HaveSupportedFileType);
        }

        private bool HaveSupportedFileType(string fileName)
        {
            return _settings.IsSupported(fileName);
        }
    }

The problem is than during request validator isn't called at all, it just skips it.问题在于根本没有调用请求验证器,它只是跳过它。 Here is my api endpoint signatrue:这是我的 api 端点签名:

        [HttpPost("{productId:min(1)}")]
        public IActionResult Upload([FromRoute] int productId, IFormFile file)
        {
          // some code here
        }

In my project I have other validators (however they don't implement AbstractValidator with Interface type) and they are doing job.在我的项目中,我有其他验证器(但是它们没有实现具有接口类型的 AbstractValidator)并且它们正在工作。 Is it even possible to validate type that implements interface?甚至可以验证实现接口的类型吗?

The problem is than during request validator isn't called at all, it just skips it.问题在于根本没有调用请求验证器,它只是跳过它。

Update更新

In addition to the manual trigger method, we can indeed let PhotoValidator function trigger automatically after submit.除了手动触发的方式,我们确实可以让PhotoValidator function在提交后自动触发

The premise is that we need to configure FluentValidation in the ConfigureServices method of startup as follow:前提是我们需要在启动的 ConfigureServices 方法中配置 FluentValidation如下:

using FluentValidation;
using FluentValidation.AspNetCore;// this need FluentValidation.AspNetCore dll
//...
public void ConfigureServices(IServiceCollection services)
{
   // ...
   services.AddMvc().AddFluentValidation();
   services.AddTransient<IValidator<FileData>, PhotoValidator>();
 }

Here is a good reference document for your reference.这是一个很好的参考文档供您参考。

Besides, to verify the content of IFormFile , you need to put it into a class as an object to verify.此外,要验证IFormFile的内容,您需要将其放入class 作为 object进行验证。

Here I created the FileData class and stored a field of IFormFile type as follows:这里我创建了FileData class 并存储了一个 IFormFile 类型的字段如下:

 public class FileData
    {
        public IFormFile file { get; set; }
    }

And, there are some details that need to be modified when verifying in PhotoValidator.并且,在 PhotoValidator 中进行验证时,还有一些细节需要修改。

When the file is null , you need to add the precondition When(f => f.file != null) to the statement that validates the Length and FileName fields, otherwise an error will occur:当文件为 null时,需要在验证Length 和 FileName字段的语句中添加前置条件When(f => f.file != null) ,否则会报错:

( Since you did not provide the relevant content of PhotoSettings , I will set _settings.MaxBytes to a fixed value here ): 由于您没有提供PhotoSettings的相关内容,我这里将 _settings.MaxBytes 设置为固定值):

 public class PhotoValidator : AbstractValidator<FileData>
    {
        private readonly PhotoSettings _settings;

        public PhotoValidator(/*PhotoSettings snapshot*/)
        {
            // _settings = snapshot;
            _settings = new PhotoSettings() { MaxBytes = 2048000 };
            RuleFor(f => f.file).NotNull().WithMessage("Please Attach your photo"); 
            RuleFor(f => f.file.Length).ExclusiveBetween(0, _settings.MaxBytes)
                .WithMessage($"File length should be greater than 0 and less than {_settings.MaxBytes / 1024 / 1024} MB")
                .When(f => f.file != null);

            RuleFor(f => f.file.FileName).Must(HaveSupportedFileType).When(f => f.file != null);
        }
        private bool HaveSupportedFileType(string fileName)
        {
            return _settings.IsSupported(fileName);
        } 
    }

Here is the controller:这是 controller:

    [HttpPost("{productId}")]
    public IActionResult Upload([FromRoute]int productId, FileData data)
    {
        string errorMessages = null;
        if (!ModelState.IsValid)
        {  
            errorMessages = ModelState.Where(x => x.Value.ValidationState == ModelValidationState.Invalid).FirstOrDefault()
                .Value.Errors.FirstOrDefault().ErrorMessage;
            return Content(errorMessages);//return error message to show in view
        } 
        return Ok();
    }

View:看法:

@{
    ViewData["Title"] = "Upload";
    Layout = "~/Views/Shared/_Layout.cshtml";
}

<h1>Upload</h1>

<form enctype="multipart/form-data" method="post">
    <div class="form-group">
        productId: <input name="productId" type="text" class="form-control" />
    </div>
    <div class="form-group">
        <input type="file" name="file" /><br />
        <span class="text-danger" id="fileMessage"></span>
    </div>
    <input id="Submit1" type="submit" value="submit" />
</form>

@section Scripts{

    <script>
        $("form").submit(function () {
            event.preventDefault();
            var productId = $("input[name=productId]").val();
            var fd = new FormData();
            var files = $('input[name=file]')[0].files[0];
            fd.append('file', files);
            var data = {
                "file": fd,
            };
            $.ajax({
                type: "post",
                url: "/" + productId,
                data: fd,
                contentType: false,
                processData: false,
                dataType: "html",
                success: function (message) {
                    $("#fileMessage").html(message);
                    if (message == "") {
                       alert("upload Success!");
                    }
                }
            })
        })
    </script>

} 

Here is the test result:这是测试结果:

在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 进行消息格式化和验证的正确方法是什么? - What is correct way to do message formatting and validation? 为每个提供商实施电子邮件验证的正确设计模式是什么? - What is the correct design pattern to implement email validation for each provider? 输入字符串的格式不正确,流畅的验证 - Input string was not in a correct format, fluent validation 使用存储库模式实现Web服务的正确方法是什么 - What's the correct way to implement a web service with the repository pattern 为值类型实现operator ++的正确方法是什么? - What's the correct way to implement operator ++ for value-types? 在枚举成员上实现流畅扩展的最佳方法 - Best way to implement fluent extension on the enum member 流畅的NHibernate,正确的方式来实现ISQLExceptionConverter - Fluent NHibernate, right way to implement ISQLExceptionConverter 这是实现MVVM的正确方法吗? - Is this correct way to implement MVVM? Fluent Validation - 有没有办法在 When 上运行异步操作? - Fluent Validation - Is there a way to run async action on When? 是否有一种标准方法可以使用 Fluent Validation 检查 HTML 内容 - Is there a standard way to check for HTML content with Fluent Validation
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM