Convert ModelState to JSON for Logging
How does it convert ModelState to JSON?
The SerializableError
Class provides this functionality.
And more importantly, how can I use what it is using?
using Microsoft.AspNetCore.Mvc;using Newtonsoft.Json;//get key(s) and error message(s) from the ModelStatevar serializableModelState = new SerializableError(ModelState);//convert to a stringvar modelStateJson = JsonConvert.SerializeObject(serializableModelState);//log itlogger.LogInformation("Bad Model State", modelStateJson);
Sample output
{ "Name": ["The Name field is required."]}
I was able to figure this out by digging through the ASP.NET Core MVC source code. The interesting part of source code from the SerializableError
class:
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); }}
Just to get a list of the error messages for each Model Property that failed validation in the manner you want as indicated above using an extension method. i.e ModelState.ToJson()
, you need create a static class with a static function ToJson(...)
. The code example will look something like this.
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); }}
The ModelState
property on every controller is normally a ModelStateDictionary
, so if we want an additional method for it, that is the class we need to extend. You can learn more about extension methods in C# by following this Link.
Let now see how to use our extension method in a sample controller action:
public IActionResult Create(UserViewModel model){ if(!ModelState.IsValid) { string json = ModelState.ToJson(); // insert code to log json to file here return BadRequest(ModelState); }}