簡體   English   中英

.Net Core Api 無法訪問 model 驗證失敗的原始值

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

我無法訪問未通過 model 驗證的原始值。 我懷疑ModelStateEntry中的AttemptedValue和/或RawValue包含原始值,但是這兩個屬性都是null

為了澄清,我寫了一個簡約的 api 來展示這個問題。

model 驗證:

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

controller:

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

驗證過濾器:

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);
        }
    }
}

當我用這個 model 調用測試方法時:

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

ValidationFilterAttribute 代碼按預期調用,但ModelStateEntry不包含原始值。 AttemptedValueRawValue都是null

Visual Studio 調試屏幕截圖

據我所知,對於 model 綁定,過濾器將調用 context.ModelState.SetModelValue 來設置 RawValue 和 AttemptedValue 的值。

但是 SystemTextJsonInputFormatter 並沒有設置它來解決這個問題,我建議你可以嘗試構建自定義擴展方法並重試。

更多細節,您可以參考以下代碼:

創建一個新的 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;
    }
}

在 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);
                });

結果:

在此處輸入圖像描述

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM