Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/asp.net/37.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# .Net核心Api无法在模型验证失败时访问原始值_C#_Asp.net_Asp.net Core_Asp.net Core Webapi - Fatal编程技术网

C# .Net核心Api无法在模型验证失败时访问原始值

C# .Net核心Api无法在模型验证失败时访问原始值,c#,asp.net,asp.net-core,asp.net-core-webapi,C#,Asp.net,Asp.net Core,Asp.net Core Webapi,我无法访问未通过模型验证的原始值。我怀疑ModelStateEntry中的AttemptedValue和/或RawValue包含原始值,但是这两个属性都null 为了澄清,我编写了一个简约的api来展示这个问题 要验证的模型: 公共类用户 { [电邮地址] 公共字符串电子邮件{get;set;} } 控制员: [ApiController] [路线(“测试”)] 公共类TestController:ControllerBase { [HttpPost] [ValidationFilter()]

我无法访问未通过模型验证的原始值。我怀疑ModelStateEntry中的AttemptedValue和/或RawValue包含原始值,但是这两个属性都null

为了澄清,我编写了一个简约的api来展示这个问题

要验证的模型:

公共类用户
{
[电邮地址]
公共字符串电子邮件{get;set;}
}
控制员:

[ApiController]
[路线(“测试”)]
公共类TestController:ControllerBase
{
[HttpPost]
[ValidationFilter()]
公共字符串测试([FromBody]用户)
{
返回用户邮箱;
}
}
验证筛选器:

public类ValidationFilterAttribute:ActionFilterAttribute,IOrderedFilter
{
公共整数顺序{get;}=int.MinValue;
重写ActionExecuting(ActionExecutingContext上下文)上的公共void
{
如果(!context.ModelState.IsValid)
{
ModelStateEntry=context.ModelState.ElementAt(0).Value;
var attemptedVal=entry.AttemptedValue;
var rawVal=entry.RawValue;
context.Result=新的OkObjectResult(rawVal);
}
}
}
当我使用此模型调用测试方法时:

{
“电子邮件”:“此处无电子邮件;)”
}
ValidationFilterAttribute代码按预期调用,但是ModelStateEntry不包含原始值。AttemptedValueRawValue都是null


据我所知,对于模型绑定,过滤器将调用context.ModelState.SetModelValue来设置RawValue和AttemptedValue的值

但是SystemTextJsonInputFormatter没有设置它来解决这个问题,我建议您可以尝试构建自定义扩展方法,然后重试

更多详细信息,请参考以下代码:

创建新的ModelStateJsonInputFormatter类:

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;
    }
}
公共类ModelStateJsonInputFormatter:SystemTextJsonInputFormatter
{
公共模型状态JSONInputFormatter(ILogger记录器、JsonOptions选项):
基本(选项、记录器)
{
}
公共重写异步任务ReadRequestBodyAsync(InputFormatterContext上下文)
{
var result=await base.ReadRequestBodyAsync(上下文);
foreach(context.ModelType.GetProperties()中的var属性)
{
var propValue=property.GetValue(result.Model,null);
var propAttemptValue=property.GetValue(result.Model,null)?.ToString();
context.ModelState.SetModelValue(property.Name、propValue、propAttemptValue);
}
返回结果;
}
}
在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);
                });
services.addcontrollerswithview(选项=>{
var serviceProvider=services.BuildServiceProvider();
var modelStateJsonInputFormatter=新modelStateJsonInputFormatter(
serviceProvider.GetRequiredService().CreateLogger(),
serviceProvider.GetRequiredService().Value);
options.InputFormatters.Insert(0,modelStateJsonInputFormatter);
});
结果: