处理 ASP.NET Core Web API 对象属性绑定

Posted

技术标签:

【中文标题】处理 ASP.NET Core Web API 对象属性绑定【英文标题】:Handling ASP.NET Core Web API object property binding 【发布时间】:2021-05-09 02:02:53 【问题描述】:

我有一个 ASP.NET Core 2.1 Web API 应用程序。如果我将空引号作为请求正文中的 json 对象属性值发送到 API 端点,我将使用 null 初始化该属性(它是 Guid 类型?)。我怎样才能改变这种行为?我需要的只是发送 BadRequest (400) 作为响应错误代码。

那是一个端点:

public async Task<ActionResult<ExampleResponse>> ExamplePatch([FromBody] ExampleModel exampleModel,
        CancellationToken cancellationToken)

    /* At this point exampleModel.ExampleGuid is initilized with null. So it should be handled before */
    /* some processing */
    return StatusCode(StatusCodes.Status201Created, ExampleResponse);

这是模型:

[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "9.10.53.0 (Newtonsoft.Json v9.0.0.0)")]
public class ExampleModel 

    /* a bunch of properties here */
    [Newtonsoft.Json.JsonProperty("exampleGuid", Required = Newtonsoft.Json.Required.Default, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
    public System.Guid? ExampleGuid  get; set; 

请求正文中的 JSON:

 ... other parameters here ..., "exampleGuid": "" 

我对此有一个限制 - 我不能向该模型属性添加属性或以某种方式更改模型。非常感谢您的帮助!

【问题讨论】:

【参考方案1】:

您可以使用 FluentValidation 包为 ExampleModel 创建验证器。 示例如下:

public class ExampleModelValidator : AbstractValidator<ExampleModel>
    
        public ExampleModelValidator()
        
            RuleFor(e => e.ExampleGuid)
                .Must(guid => guid.ToString().lenght > 0)
                 .When(e => e.ExampleGuid.HasValue)
                 .WithMessage("Must be a valid GUID");

        
    

这将在端点正文之前验证您的模型。

另外,我个人喜欢在我的 Startup.cs 中添加这段代码:

public void ConfigureServices(IServiceCollection services)
    
        services
            
            .AddFluentValidation(fv => fv.RegisterValidatorsFromAssemblyContaining<ExampleModelValidator>())
            .ConfigureApiBehaviorOptions(options =>
            
                options.InvalidModelStateResponseFactory = context =>
                
                    var errorsList = string.Join(" | ", context.ModelState.Values.SelectMany(v => v.Errors).Select(err => err.ErrorMessage).ToArray());
                    return new BadRequestObjectResult(errorsList);
                ;
            );
    

这将返回由管道和 BadRequest 分隔的所有验证消息作为响应。

【讨论】:

但是在 ConfigureServices 中你应该调用 AddMvc 来使用 AddFluentValidation 并且 ConfigureApiBehaviorOptions 在 asp.net core 2.1 中不存在。我试过 FluentValidation 但 Guid?可以为空,这是正确的用例。但是发送空引号是不正确的,应该用 400 错误代码来响应。 AddMvc 不应该给你带来任何问题,我也在使用它。 ConfigureApiBehaviorOptions 对我来说很方便将所有错误与管道分开,但你也可以不用它。关于null,如果不为null,你也可以检查是否为空字符串,我会更新我的答案 感谢您的回复!我发现进行此类验证或自定义模型绑定的直接方法是创建自定义 IModelBinder 和 IModelBinderProvider (docs.microsoft.com/ru-ru/aspnet/core/mvc/advanced/…),我可以在其中放置验证逻辑。我可以使用过滤器或/并且只解析来自 HttpContext 的原始 json。但更好的是更改开放的 api 规范以更符合要求,并且 nswag 可以生成具有适当约束属性的许多正确代码。

以上是关于处理 ASP.NET Core Web API 对象属性绑定的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core Web API下事件驱动型架构的实现:一个简单的实现

ASP.NET Core Web API

ASP.NET Core Web API DELETE 调用返回 405

对 Web api 的 ASP.NET Core 应用程序 http 客户端请求

ASP.NET Core Web API InvalidOperationException:无法解析服务 [重复]

ASP.NET Core Web API + Angular 对预检请求的响应未通过访问控制检查:预检请求不允许重定向