[英].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 :
AttemptedValue和RawValue都是null :
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.