扩展 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 的扩展名仍然 returns 为空。有任何想法吗? :))
这就是我使用扩展程序的方式:
[HttpPost]
[Route("myrequest")]
public async Task<IActionResult> MyRequest([FromBody] MyRequestType request)
{
if (!ModelState.IsValid) {
Logger.LogThis(ModelState.ToLoggingFormat());
}
}
试试这个:
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}");
}
}
未测试...
这个问题发生在 JsonInputFormatter
。在 Asp.Net Core 中,有两种方法可以将请求绑定到模型,FromForm
使用模型绑定,FromBody
使用 JsonInputFormatter
。对于模型绑定,它调用 context.ModelState.SetModelValue
来设置 RawValue
和 AttemptedValue
的值。但是,JsonInputFormatter
没有实现此功能。
您需要通过自定义 JsonInputFormatter
来实现此功能,例如
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;
}
}
注册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);
我为 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 的扩展名仍然 returns 为空。有任何想法吗? :))
这就是我使用扩展程序的方式:
[HttpPost]
[Route("myrequest")]
public async Task<IActionResult> MyRequest([FromBody] MyRequestType request)
{
if (!ModelState.IsValid) {
Logger.LogThis(ModelState.ToLoggingFormat());
}
}
试试这个:
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}");
}
}
未测试...
这个问题发生在 JsonInputFormatter
。在 Asp.Net Core 中,有两种方法可以将请求绑定到模型,FromForm
使用模型绑定,FromBody
使用 JsonInputFormatter
。对于模型绑定,它调用 context.ModelState.SetModelValue
来设置 RawValue
和 AttemptedValue
的值。但是,JsonInputFormatter
没有实现此功能。
您需要通过自定义 JsonInputFormatter
来实现此功能,例如
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; } }
注册
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);