1

Closed

GetErrorContext prevents wrapping of exceptions

description

Hi,

We have some code that uses JSON.Net to deserialise an Ext.Direct request in an IHttpHandler.
Some of the parameters have their own custom deserialisers that perform validation for the class in question, for a BIC or IBAN say.
These can throw exceptions.

If we wrap an exception during one of these calls JSON.Net's GetErrorContext throws its own exception, due to _currentErrorContext.Error != error, with the message: "Current error context error is different to requested error."

I believe it should be possible to disable this check, and would rather not have to modify the source myself.

Out of interest, what's it for anyway?

Regards,
Westy
Closed Dec 22, 2013 at 9:18 AM by JamesNK
Fixed

comments

JamesNK wrote Apr 13, 2013 at 10:32 PM

Could you attach an example of what you are doing?

westy wrote Jun 19, 2013 at 2:42 PM

Hi James,

Sorry I didn't get back to you, been up against it, and still am to be honest.
Have just had this exception again... will try and find the time to come up with an example.

It's very annoying though. It basically happens when deserialisation fails for something, but the error is wrapped with a nice "talking to users rather than developers" message.

My question stands though, what is the check for?

Regards,
Westy

JamesNK wrote Dec 11, 2013 at 1:15 PM

** Closed by JamesNK 30/04/2013 01:51

westy wrote Dec 11, 2013 at 1:20 PM

Ok, have been asked to look at this again, since we get them logged often in our application.

Here's some code I have knocked up that exhibits the behaviour.
Basically it involves an object with a custom converter that contains an object with a custom converter, and the top-level one wraps the exception, for whatever reason.

Easier to see here:
using System;
using Newtonsoft.Json;

namespace JSON.Net_Context_Error
{
    /// <summary>
    /// This could be an object we are passing up in an interface.
    /// </summary>
    [JsonConverter(typeof(SomethingConverter))]
    public class Something
    {
        public class SomethingConverter : JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                return true;
            }

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                try
                {
                    // Do own stuff.
                    // Then call deserialise for inner object.
                    var innerObject = serializer.Deserialize(reader, typeof(SomethingElse));

                    return null;
                }
                catch (Exception ex)
                {
                    // If we get an error wrap it in something less scary.
                    throw new Exception("An error occurred.", ex);
                }
            }

            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                throw new NotImplementedException();
            }
        }

        public SomethingElse SomethingElse { get; set; }

        public Something()
        {
            this.SomethingElse = new SomethingElse();
        }
    }

    /// <summary>
    /// This is an object that is contained in the interface object.
    /// </summary>
    [JsonConverter(typeof(SomethingElseConverter))]
    public class SomethingElse
    {
        public class SomethingElseConverter : JsonConverter
        {
            public override bool CanConvert(Type objectType)
            {
                return true;
            }

            public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                throw new NotImplementedException();
            }

            public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
            {
                throw new NotImplementedException();
            }
        }

    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                var serialiser = JsonSerializer.Create(new JsonSerializerSettings() { });

                string foo = "{ somethingElse: 0 }";
                var reader = new System.IO.StringReader(foo);

                serialiser.Deserialize(reader, typeof(Something));
            }
            catch (Exception ex)
            {
                Console.Error.WriteLine(ex.ToString());
            }
        }
    }
}
We have objects with deserialisers that validate a string against a regex, say.
That throws an exception that gets logged with the full details.
The user, however, gets given a nicer exception... at least that's the plan.

We've worked around the issue in places, but as I say, still see this.

I'm curious as to what the check is meant to guard against.
I don't think you should stop people wrapping exceptions in converters, if that is what they want to do.

Cheers,
Westy

westy wrote Jan 24 at 4:40 PM

Hi James,

Thanks for addressing this.
It's getting close to our next release and we really need this fix in there.

What are your plans for your next release? Is one coming soon?

Failing that going to have to patch our existing version, Json45r11 with the fix.
Any chance you could briefly explain what you have done?
Is it just a case of removing the check and exception throwing from JsonSerializerInternalBase.GetErrorContext, or is there more to it than that?

Cheers,
Westy