Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception message change in latest version

I just updated Newtonsoft.Json library from 4.5.1 to 5.0.8. What I noticed is that one of the exception messages changed. Once the value can't be deserialized, the following is contained in my 400 response, "Error converting value...". Now, this message was different in the 4.5.1. version of the lib. The problem is that the full name of the object is exposed and that is for me an undesirable behavior.

In order to clarify:

The problem is the following. Till the version 4.5.1 of the Newtonsoft.Json library, once the JsonSerializationException was thrown, the message in the response just specified that a certain object was unable to be serialized. From that version on, the library in the response message, yes it includes the error message but also the full name of the object that it failed to serialize to. That's a pity as I would not like to expose the namespace in the error message to the outside world.

I was just checking the source code of the JSON lib and I found that the code in StringEnumConverter now is:

catch (Exception ex)
{
    throw JsonSerializationException.Create(reader, "Error converting value {0} to type '{1}'.".FormatWith(CultureInfo.InvariantCulture, MiscellaneousUtils.FormatValueForPrint(reader.Value), objectType), ex);
}

meanwhile it was throwing the default Enum.Parse ArgumentException with the message "Must specify valid information for parsing in the string." before.

Now, I preferred this message as it was not showing to the users the internal namespace of my API.

I tried to hook up the event JsonFormatter.SerializerSettings.Error in my Application_Start method, however I was unable to do what I intended to do. I had a chance to access to get to the exception I meant to process,

private static void Error(object sender, ErrorEventArgs errorEventArgs)
{
    if (errorEventArgs.ErrorContext.Error.GetType() == typeof(JsonSerializationException))
    {

but all the properties are read only and objects that I thought to modify are marked as internal. Re-throwing an exception is also not a case.

For clarity, take a look on StringEnumConverter and JsonSerializerInternalBase classes in Newtonsoft.Json.Net40 project.

Do you have any idea where to hook the library in question in order to override the error message? Or any other idea on how to solve the problem (stop showing the full namespace in the error messages)?

My question is, can I somehow re-throw an exception with specifying a different message, somewhere like the one in the 4.5.1?

like image 240
MaiOM Avatar asked Jan 03 '14 15:01

MaiOM


People also ask

How do I write an exception message?

When something goes wrong in your program, you can throw an exception in your code with a message that describes a problem. Typical example: throw new Exception("Houston we have a problem");

What does exception message mean?

Exception messages depend on the transaction being carried out and are meant to inform you of an important or critical event (for example, start date lies in the past, safety stock has been exceeded). By means of the exception messages, you can easily sort out any materials that you need to reprocess manually.

Should exception messages end with period?

Use grammatically correct error messages Write clear sentences and include ending punctuation. Each sentence in the string assigned to the Exception. Message property should end in a period.

How do I read an exception message in C#?

C# provides built-in support to handle the exception using try , catch & finally blocks. try block: Any suspected code that may raise exceptions should be put inside a try{ } block. During the execution, if an exception occurs, the flow of the control jumps to the first matching catch block.


1 Answers

After a while I found a solution that works. I basically created a new converter that derived from StringEnumConverter and override the ReadJson method.

My new converter looks like this:

public class StringEnumConverterEx : StringEnumConverter
    {
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            // the message in the response, once an serialization exception is thrown, after the version 4.5.1 of Newtonsoft.JSON library,
            // has changed. As we do not want to expose the full namespace of our Enums, we are catching the exception and re-throwing it
            // with a different message.
            try
            {
                return base.ReadJson(reader, objectType, existingValue, serializer);
            }
            catch (JsonSerializationException)
            {
                string values = objectType.IsEnum ? String.Join(",", Enum.GetNames(objectType)) : string.Empty;

                throw new JsonSerializationException(string.Format("Error converting value {0}, possible values are: {1}",
                    objectType.Name, values));
            }
        }
    }

Now I just add this converter instead of the original one StringEnumConverter on my app start.

GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new StringEnumConverterEx());

This does the trick and overrides the exception message. As you can see, I do also offer in the message the possible values for that Enum.

Hope that this will help someone else.

Cheers

like image 112
MaiOM Avatar answered Oct 04 '22 03:10

MaiOM