15

We have ASP.NET Core application which we use as a REST api. Methods use [FromBody]MyClass param as input. Problem is if the client sends an invalid JSON string the input value becomes null due to JSON serialization errors. Is there a way to log such errors?

Edit: I'm looking for application-wide solution not per-method..

4
  • 2
    Possible duplicate of ASP.Net 5 MVC 6 - how to return invalid JSON message on POST using FromBody? Commented Oct 26, 2017 at 7:41
  • @Kirk: This is not the same question. The linked question asks how to return json errors to the caller and the accepted answer is per-method basis solution. I'm looking to catch and log them application-wide. Commented Oct 26, 2017 at 12:01
  • 1
    Did you read the second, non-accepted answer that describes how to use a filter to do exactly what you are asking for? Commented Oct 26, 2017 at 12:15
  • @Kirk: I did not see that, my bad. I've solved what I'm looking for differently, thanks for pointing it out. Commented Oct 26, 2017 at 13:42

2 Answers 2

13

I've solved this with adding an error handler in Startup.cs:

services.AddMvc()
        .AddJsonOptions(options => {
              options.SerializerSettings.Error = (object sender, Newtonsoft.Json.Serialization.ErrorEventArgs args) =>
              {
                    //Log args.ErrorContext.Error details...
              };
        });
Sign up to request clarification or add additional context in comments.

2 Comments

Yes, I agree, but how do you log it when you inject LoggerFactoryManager.Init(_); in the same ConfigureServices method?
var logger = LoggerFactoryManager.GetLogger<JsonSerializerSettings>(); logger.LogWarning("Failed to deserialize JSON on input: " + args.ErrorContext.Error.Message);
-1

You can use an action filter to capture any model binding error (including deserialization errors). You can pull the error from the ActionExecutingContext.

EDIT: To use this approach, You need to suppress the model state invalid filter because by default web api will automatically return a 400 if there is a binding error. https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.mvc.apibehavioroptions.suppressmodelstateinvalidfilter#microsoft-aspnetcore-mvc-apibehavioroptions-suppressmodelstateinvalidfilter

    public class LogModelBindingErrorFilter : IActionFilter
    {
        private readonly ILogger _logger = LogManager.GetCurrentClassLogger();

        public void OnActionExecuting(ActionExecutingContext context)
        {
            if (!context.ModelState.IsValid)
            {
                var messages = context.ModelState.Values
                    .SelectMany(x => x.Errors)
                    .Where(x => x.Exception is JsonException)
                    .Select(x => x.ErrorMessage);

                _logger.Log(LogLevel.Error, string.Join(", ", messages));
            }
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
        }
    }

2 Comments

Json deserialization error will happen before ActionFilters. Those are called after model binding. This will not be called. learn.microsoft.com/en-us/aspnet/core/mvc/controllers/filters
@PekkaYlenius Yes, model binding happens before action filters, but the errors that occur during model binding are stored in ModelState so it can be inspected later. learn.microsoft.com/en-us/aspnet/core/mvc/models/… stackoverflow.com/a/49245960/7810515

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.