将ModelState转换为JSON以便记录

9
我该如何将 ModelState 转换为与 ASP.NET Core 相同格式的 JSON?
我知道可以使用 BadRequest(ModelState) 将其转换为 JSON 并返回给客户端。但是,它是如何将 ModelState 转换为 JSON 的?更重要的是,我应该如何使用它所使用的方法?
我的目标是将 ModelState 以 JSON 格式记录在我们的日志“文件”中。
例如: var blah = ModelState.ToJson()

4
JSON.NET是内置的。ASP.NET Core使用它来将对象序列化为响应,所以你可以简单地做同样的事情:JsonCovert.SerializeObject(ModelState) - Chris Pratt
嗨@ChrisPratt - 这会序列化整个对象。ASP.NET返回一个更干净的版本:{ "Name": [ "The Name field is required." ] } - spottedmahn
1
那就使用 ModelState.Errors - Chris Pratt
顺便说一下,没有 ModelState.Errors。但是每个字典条目都有一个 Errors 属性。无论哪种方式,输出的信息都太多了。不过,SerializableError 提供了我需要的内容!@ChrisPratt - spottedmahn
2个回答

15
它如何将ModelState转换为JSON? SerializableError类提供了这个功能。
更重要的是,我如何使用它所使用的内容?
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;

//get key(s) and error message(s) from the ModelState
var serializableModelState = new SerializableError(ModelState);

//convert to a string
var modelStateJson = JsonConvert.SerializeObject(serializableModelState);

//log it
logger.LogInformation("Bad Model State", modelStateJson);

样例输出

{
    "Name": ["The Name field is required."]
}

我通过挖掘ASP.NET Core MVC源代码来解决了这个问题。从SerializableError类的源代码中发现有趣的部分:

foreach (var keyModelStatePair in modelState)
{
    var key = keyModelStatePair.Key;
    var errors = keyModelStatePair.Value.Errors;
    if (errors != null && errors.Count > 0)
    {
        var errorMessages = errors.Select(error =>
        {
            return string.IsNullOrEmpty(error.ErrorMessage) ?
                Resources.SerializableError_DefaultError : error.ErrorMessage;
        }).ToArray();

        Add(key, errorMessages);
    }
}

1
为了按照上述方式获取每个模型属性的错误消息列表,您需要使用扩展方法。例如ModelState.ToJson(),您需要创建一个静态类,并在其中创建一个静态函数ToJson(...)。代码示例如下:
public static class ModelStateExtensions
{
    /// <summary>
    /// Reads all the error messages in a <see cref="ModelStateDictionary"/> as 
    /// a collection and returns a JSON <see cref="string"/> of the list.
    /// </summary>
    /// <param name="modelstate">Current modelstate assuming that you've checked
    /// and confirmed that is Invalid using <see 
    /// cref="ModelStateDictionary.IsValid"/>
    /// </param>
    /// <returns>
    /// Collection of validation errors for the model as a JSON string.
    /// </returns>
    public static string ToJson(this ModelStateDictionary modelstate)
    {
        List<string> errors = modelstate.Values
                                        .SelectMany(x => x.Errors)
                                        .Select(x => x.ErrorMessage)
                                        .ToList();
        return JsonConvert.SerializeObject(errors);
    }
}

每个控制器上的“ModelState”属性通常是一个“ModelStateDictionary”,因此,如果我们想要一个附加方法,那么这就是我们需要扩展的类。您可以通过访问此Link来了解有关C#扩展方法的更多信息。
现在让我们看看如何在示例控制器操作中使用我们的扩展方法:
public IActionResult Create(UserViewModel model)
{
    if(!ModelState.IsValid)
    {
        string json = ModelState.ToJson();

        // insert code to log json to file here

        return BadRequest(ModelState);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接