如何用LINQ简化ASP.NET Core中ModelState验证错误日志的嵌套循环?
使用LINQ简化ASP.NET Core模型验证错误日志代码
背景
- 我有一个ASP.NET Core应用,需要将服务器端验证错误写入日志。
- 当ASP.NET Core模型检测到表单字段存在错误时,
ModelState.IsValid会返回false。 - 表单所有字段都包含在
ModelState.Values中。 - 如果某个字段对应的Value存在一个或多个错误,
Value.Errors.Count会大于0。 - 我需要记录:a) 表单字段名称(对应Value的key);b) 该字段的每条错误信息。
- 希望把这些信息整合成单个C#字符串。
当前代码
// 日志输出示例: // 2022-10-24 09:37:29.0909|Error|ServiceMenu.Q255: 值''无效。 // 2022-10-24 09:37:35.4096|Error|ServiceMenu.Q265: 值''无效。 if (!ModelState.IsValid) { foreach (var k in ModelState.Keys) { var v = ModelState[k]; if (v.Errors.Count > 0) { string s = k + ": "; for (int i=0; i < v.Errors.Count - 1; i++) s += v.Errors[i].ErrorMessage + ", "; s += v.Errors[v.Errors.Count - 1].ErrorMessage; _logger.LogError(s); } } return Page(); }
示例输出(两个必填字段Q255和Q265为空时)
2022-10-24 09:37:29.0909|Error|ServiceMenu.Q255: 值''无效。 2022-10-24 09:37:35.4096|Error|ServiceMenu.Q265: 值''无效。
解决方案:用LINQ简化代码
当然可以用LINQ简化这段嵌套循环,核心是通过LINQ筛选错误字段、拼接错误信息,代替手动嵌套循环的逻辑。
简化后的代码如下:
if (!ModelState.IsValid) { var errorMessages = ModelState .Where(kv => kv.Value.Errors.Any()) .Select(kv => $"{kv.Key}: {string.Join(", ", kv.Value.Errors.Select(e => e.ErrorMessage))}"); foreach (var msg in errorMessages) { _logger.LogError(msg); } return Page(); }
代码说明:
Where(kv => kv.Value.Errors.Any()):筛选出所有存在验证错误的字段键值对Select(kv => $"{kv.Key}: {string.Join(", ", kv.Value.Errors.Select(e => e.ErrorMessage))}"):将字段名与该字段的所有错误信息用逗号拼接成标准日志字符串- 最后遍历生成的错误信息集合,逐一写入日志
这段代码和原代码逻辑完全一致,但更简洁易读,用LINQ替代了手动的嵌套循环和字符串拼接操作。
内容的提问来源于stack exchange,提问作者paulsm4
相关产品推荐
相关产品推荐

