将 ModelState 转换为 JSON 以进行日志记录

Posted

技术标签:

【中文标题】将 ModelState 转换为 JSON 以进行日志记录【英文标题】:Convert ModelState to JSON for Logging 【发布时间】:2019-01-31 06:40:26 【问题描述】:

如何将ModelState 转换为与 ASP.NET Core 相同格式的 JSON?

我知道我可以做到BadRequest(ModelState),它会将 JSON 返回给客户端。它如何将ModelState 转换为 JSON?更重要的是,我该如何使用它正在使用的东西

我的目标是将ModelState 作为 JSON 记录在我们的日志“文件”中。

var blah = ModelState.ToJson()

【问题讨论】:

JSON.NET 是内置的。这是 ASP.NET Core 用来序列化响应对象的方法,所以你可以简单地做同样的事情:JsonCovert.SerializeObject(ModelState) 嗨@ChrisPratt - 序列化整个对象。 ASP.NET 返回更简洁的版本: "Name": [ "The Name field is required." ] 然后使用ModelState.Errors 仅供参考,没有ModelState.Errors。显然,每个字典条目都有一个 Errors 属性。无论哪种方式都会输出太多信息。 SerializableError 提供了我正在寻找的东西! @ChrisPratt 【参考方案1】:

它如何将 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 source code 来解决这个问题。 source code 的有趣部分来自 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);
    

【讨论】:

【参考方案2】:

只是为了获取每个模型属性的错误消息列表,这些模型属性以您想要的方式验证失败,如上所述,使用扩展方法。即ModelState.ToJson(),您需要创建一个带有静态函数ToJson(...)static 类。代码示例将如下所示。

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

【讨论】:

以上是关于将 ModelState 转换为 JSON 以进行日志记录的主要内容,如果未能解决你的问题,请参考以下文章

将 JSON 转换为 NSData 以进行归档

将 swift 数组转换为对象以进行 json 序列化

如何将 JSON 转换为 Swift Dictionary 以进行 HTTP POST

将拼花地板转换为json以进行dynamodb导入

将字符串转换为原始字符串以进行 json 处理 [Python]

如何将带单引号的字符串转换为双引号以进行 json 解析