Convert ModelState to JSON for Logging Convert ModelState to JSON for Logging json json

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