You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Fluent Validation遇输入首尾带\时抛出System.ArgumentNullException求助

问题

在应用中使用Fluent Validation校验用户输入时发现:当输入字符串首尾带有\字符(如" ferrari\ "或" \ferrari ")时,校验失败并抛出System.ArgumentNullException异常;移除该字符或放置在其他位置时,校验正常。

使用的校验规则如下:

RuleFor(cb => cb.Address)
.NotEmpty().WithMessage("The Address field is required.")
.Matches("^[a-zA-Z0-9 ]+$").WithMessage("The Address field must contain only letters and numbers.");

完整错误日志:

System.ArgumentNullException: Cannot pass null model to Validate. (Parameter 'instanceToValidate')
   at FluentValidation.AbstractValidator`1.EnsureInstanceNotNull(Object instanceToValidate) in /Users/jskinner/code/FluentValidation/src/FluentValidation/AbstractValidator.cs:line 516
   at FluentValidation.AbstractValidator`1.ValidateAsync(ValidationContext`1 context, CancellationToken cancellation) in /Users/jskinner/code/FluentValidation/src/FluentValidation/AbstractValidator.cs:line 247
   at ecommerce.Controllers.AuthController.Login(DTO_CustomerLogin customer) in D:\Lavoro\ecommerce\ecommerce\ecommerce\Controllers\AuthController.cs:line 30
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Rethrow(ActionExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.InvokeInnerFilterAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextResourceFilter>g__Awaited|25_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Rethrow(ResourceExecutedContextSealed context)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.InvokeFilterPipelineAsync()
--- End of stack trace from previous location ---
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeAsync>g__Awaited|17_0(ResourceInvoker invoker, Task task, IDisposable scope)
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.<Invoke>g__AwaitRequestTask|6_0(Endpoint endpoint, Task requestTask, ILogger logger)
   at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
   at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
   at Swashbuckle.AspNetCore.SwaggerUI.SwaggerUIMiddleware.Invoke(HttpContext httpContext)
   at Swashbuckle.AspNetCore.Swagger.SwaggerMiddleware.Invoke(HttpContext httpContext, ISwaggerProvider swaggerProvider)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)

HEADERS
=======

Accept: */*
Host: localhost:7298
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36 OPR/98.0.0.0
:method: POST
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Content-Type: application/json-patch+json
Cookie: wordpress_test_cookie=WP%20Cookie%20check,wordpress_logged_in_743590ba59234b9fc8eaaf393199b671=admin%7C1685559922%7C2IGA4sVh57u8X2IiPvPH55IiFpWW8Bbh7A6bJeAOPCY%7C5922389646a2f0cdae23863404146ff7a36b7e4ec26b2cee87d6495403b7c9c2,tk_ai=woo%3A7xGM8dng5IbSM3DfhUjxnCMi,wp-settings-time-1=1685387348
Origin: https://localhost:7298
Referer: https://localhost:7298/swagger/index.html
Content-Length: 48
sec-ch-ua: "Chromium";v="112", "Not_A Brand";v="24", "Opera GX";v="98"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
sec-fetch-site: same-origin
sec-fetch-mode: cors
sec-fetch-dest: empty

解决方案

异常原因分析

这个异常并非Fluent Validation的校验逻辑抛出,而是模型绑定阶段出错:JSON中的\是转义字符,当输入首尾出现未正确转义的\时,JSON解析器无法正确解析请求体,导致控制器接收的DTO_CustomerLogin实例为null。Fluent Validation校验null模型时,就会触发ArgumentNullException。

具体解决步骤

  1. 修正JSON输入格式
    确保前端传入的JSON合法,所有\必须转义为\\。如果是用Swagger测试,手动输入时要把\写成\\,否则Swagger会将单个\当作转义符处理,导致JSON格式错误。

  2. 添加控制器前置校验
    在控制器方法中先判断传入的模型是否为null,提前返回错误响应,避免进入Fluent Validation流程:

    [HttpPost]
    public async Task<IActionResult> Login(DTO_CustomerLogin customer)
    {
        if (customer == null)
        {
            return BadRequest("请求体格式无效,请检查输入内容。");
        }
        // 执行Fluent Validation校验
        var validationResult = await _validator.ValidateAsync(customer);
        if (!validationResult.IsValid)
        {
            return BadRequest(validationResult.Errors);
        }
        // 后续业务逻辑
        // ...
    }
    
  3. 优化Fluent Validation规则(可选)
    若需要明确禁止输入\字符,可保留现有正则规则(已排除\),同时添加NotNull规则增强容错:

    RuleFor(cb => cb.Address)
        .NotNull().WithMessage("地址字段不能为空。")
        .NotEmpty().WithMessage("地址字段不能为空。")
        .Matches("^[a-zA-Z0-9 ]+$").WithMessage("地址字段只能包含字母、数字和空格。");
    
  4. 配置JSON解析器容错(可选)
    在ASP.NET Core的Program.cs中配置JSON解析器,处理非法转义的情况,避免模型绑定为null:

    builder.Services.AddControllers()
        .AddJsonOptions(options =>
        {
            // 忽略注释、允许 trailing commas
            options.JsonSerializerOptions.ReadCommentHandling = JsonCommentHandling.Skip;
            options.JsonSerializerOptions.AllowTrailingCommas = true;
            // 若使用Newtonsoft.Json,可配置错误处理
            // options.UseNewtonsoftJson(settings =>
            // {
            //     settings.Error = (sender, args) => args.ErrorContext.Handled = true;
            // });
        });
    

内容的提问来源于stack exchange,提问作者Petruz21

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 15:40:20