简体   繁体   English

.Net Core Api 无法访问 model 验证失败的原始值

[英].Net Core Api cannot access original value on model validation failures

I cannot access the original value that didn't pass the model validation.我无法访问未通过 model 验证的原始值。 I would suspect AttemptedValue and/or RawValue in ModelStateEntry to contain the original value, however both properties are null .我怀疑ModelStateEntry中的AttemptedValue和/或RawValue包含原始值,但是这两个属性都是null

For clarification, I wrote a minimalistic api, to showcase the issue.为了澄清,我写了一个简约的 api 来展示这个问题。

The model to validate: model 验证:

public class User
{
    [EmailAddress]
    public string Email { get; set; }
}

The controller: controller:

[ApiController]
[Route("test")]
public class TestController : ControllerBase
{
    [HttpPost]
    [ValidationFilter()]
    public string Test([FromBody] User user)
    {
        return user.Email;
    }
}

The validation filter:验证过滤器:

public class ValidationFilterAttribute : ActionFilterAttribute, IOrderedFilter
{
    public int Order { get; } = int.MinValue;

    override public void OnActionExecuting(ActionExecutingContext context)
    {
        if (!context.ModelState.IsValid)
        {
            ModelStateEntry entry = context.ModelState.ElementAt(0).Value;
            var attemptedVal = entry.AttemptedValue;
            var rawVal = entry.RawValue;
            context.Result = new OkObjectResult(rawVal);
        }
    }
}

When I call the test method with this model:当我用这个 model 调用测试方法时:

{
    "email": "No email here ;)"
}

The ValidationFilterAttribute code is called as expected, however the ModelStateEntry does not contain the original value. ValidationFilterAttribute 代码按预期调用,但ModelStateEntry不包含原始值。 Both AttemptedValue and RawValue are null : AttemptedValueRawValue都是null

Visual Studio debugging screenshot Visual Studio 调试屏幕截图

As far as I know, for model binding, the filter will calls context.ModelState.SetModelValue to set value for RawValue and AttemptedValue.据我所知,对于 model 绑定,过滤器将调用 context.ModelState.SetModelValue 来设置 RawValue 和 AttemptedValue 的值。

But the SystemTextJsonInputFormatter doesn't set it to solve this issue, I suggest you could try to build custom extension method and try again.但是 SystemTextJsonInputFormatter 并没有设置它来解决这个问题,我建议你可以尝试构建自定义扩展方法并重试。

More details, you could refer to below codes:更多细节,您可以参考以下代码:

Create a new ModelStateJsonInputFormatter class:创建一个新的 ModelStateJsonInputFormatter class:

public class ModelStateJsonInputFormatter : SystemTextJsonInputFormatter
{
    public ModelStateJsonInputFormatter(ILogger<ModelStateJsonInputFormatter> logger, JsonOptions options) : 
        base(options ,logger)
    {
    }
    public override async Task<InputFormatterResult> ReadRequestBodyAsync(InputFormatterContext context)
    {
        var result = await base.ReadRequestBodyAsync(context);
        foreach (var property in context.ModelType.GetProperties())
        {
            var propValue = property.GetValue(result.Model, null);
            var propAttemptValue = property.GetValue(result.Model, null)?.ToString();
            context.ModelState.SetModelValue(property.Name, propValue, propAttemptValue);
        }
        return result;
    }
}

Reigster it in startup.cs:在 startup.cs 中重新注册它:

            services.AddControllersWithViews(options => {
                var serviceProvider = services.BuildServiceProvider();
                var modelStateJsonInputFormatter = new ModelStateJsonInputFormatter(
            serviceProvider.GetRequiredService<ILoggerFactory>().CreateLogger<ModelStateJsonInputFormatter>(),
serviceProvider.GetRequiredService<IOptions<JsonOptions>>().Value);
                options.InputFormatters.Insert(0, modelStateJsonInputFormatter);
                });

Result:结果:

在此处输入图像描述

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM