繁体   English   中英

扩展 ModelState 以输出我自己的消息 - 如何获取模型状态值

[英]Extending ModelState to output my own message - how do I get model state value

我为 ModelStateDictionary 编写了自己的扩展,但遇到了显示输入值的问题。

这是我的尝试:

public static string ToLoggingFormat(this ModelStateDictionary modelState)
{
    var sb = new StringBuilder();
    sb.AppendLine("Input validation error occurred:");

    foreach (var ms in modelState.Values)
    {
        foreach (ModelError error in ms.Errors)
        {
            sb.AppendLine(error.ErrorMessage);
        }

        if (!string.IsNullOrEmpty(ms.AttemptedValue)) { 
            sb.AppendLine($"Attempted Value: {ms.AttemptedValue}");
        }
    }

    return sb.ToString();
}

我的问题是 ms.AttemptedValue 始终为空。 请问有什么想法吗? 我也试过 ms.RawValue 但这也是空的。 我传入的值无效,因为它超出了限制,因此不为空。


我正在按照建议添加自定义 XML 输入格式化程序!

public class ModelStateXmlInputFormatter : XmlSerializerInputFormatter
{
    public ModelStateXmlInputFormatter(MvcOptions options) : base(options)
    {
    }
    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;
    }

我这样添加,

services.AddMvc(options =>
{
    // Remove JSON input
    options.OutputFormatters.RemoveType(typeof(JsonOutputFormatter));
    options.InputFormatters.RemoveType(typeof(JsonInputFormatter));
    options.ReturnHttpNotAcceptable = true;

    // Add our customer XmlInputFormatter
        options.InputFormatters.Add(new ModelStateXmlInputFormatter(options));
        options.OutputFormatters.Add(new XmlSerializerOutputFormatter());

})
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

但是扩展仍然为 ms.AttemptedValue 返回 null。 有任何想法吗? :))

这就是我使用扩展的方式:

[HttpPost]
[Route("myrequest")]
public async Task<IActionResult> MyRequest([FromBody] MyRequestType request)
{
    if (!ModelState.IsValid) {
          Logger.LogThis(ModelState.ToLoggingFormat());
    }
}

对于这个问题,它发生在JsonInputFormatter 在Asp.Net核心,有两种方法可以结合requst到模型, FromForm与模型结合和FromBodyJsonInputFormatter 对于模型绑定,它调用context.ModelState.SetModelValue来设置RawValueAttemptedValue值。 但是, JsonInputFormatter没有实现这个功能。

您需要通过自定义JsonInputFormatter来实现此功能,例如

  1. ModelStateJsonInputFormatter

     public class ModelStateJsonInputFormatter : JsonInputFormatter { public ModelStateJsonInputFormatter(ILogger<ModelStateJsonInputFormatter> logger, JsonSerializerSettings serializerSettings, ArrayPool<char> charPool, ObjectPoolProvider objectPoolProvider, MvcOptions options, MvcJsonOptions jsonOptions) : base(logger, serializerSettings, charPool, objectPoolProvider, options, jsonOptions) { } 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; } }
  2. 注册ModelStateJsonInputFormatter

     services.AddMvc(opt => { var serviceProvider = services.BuildServiceProvider(); var modelStateJsonInputFormatter = new ModelStateJsonInputFormatter( serviceProvider.GetRequiredService<ILoggerFactory>().CreateLogger<ModelStateJsonInputFormatter>(), serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Value.SerializerSettings, serviceProvider.GetRequiredService<ArrayPool<char>>(), serviceProvider.GetRequiredService<ObjectPoolProvider>(), opt, serviceProvider.GetRequiredService<IOptions<MvcJsonOptions>>().Value ); opt.InputFormatters.Insert(0, modelStateJsonInputFormatter); }).SetCompatibilityVersion(Microsoft.AspNetCore.Mvc.CompatibilityVersion.Latest);

尝试这个:

foreach (var ms in modelState.Keys)
    {
        var value = modelState[ms];
        foreach (ModelError error in value.Errors)
        {
            sb.AppendLine(error.ErrorMessage);
        }

        if (!string.IsNullOrEmpty(value.Value.AttemptedValue)) { 
            sb.AppendLine($"Attempted Value: {value.Value.AttemptedValue}");
        }
    }

未测试...

我知道这已经有两个月了,但是我正在尝试从modelstate获取tryedvalue,该值似乎没有由JsonInputFormatter填充。

淘周的答案很接近,但是由于模型无效而失败了。 查看JsonInputFormatter的源代码,它似乎是从MetaData中提取值的,但是对我而言,我无法确定如何从上下文中获取值。

有任何想法吗?

暂无
暂无

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

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