question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

IAdvancedBus.Get<Interface> fails with serialization exception

See original GitHub issue

Description

When calling IAdvancedBus.Get<T> with an interface parameter type, instanced to a class containing Struct types, a serialization exception is thrown. This is inconsistent with the behavior of Consume method that allows proper deserialization of such examples.

Expected behavior IAdvancedBus.Get allows deserializing such types correctly.

Possible root cause https://github.com/EasyNetQ/EasyNetQ/blob/master/Source/EasyNetQ/BasicGetResult.cs specifies a where T : class constraint on type, which excludes Struct types (like int) from serialization. https://github.com/EasyNetQ/EasyNetQ/blob/a1d28cca528d6675b90960a8e6f410f0515ce559/Source/EasyNetQ/IMessage.cs does not.

Possible partial workaround Serialization will be performed correctly if a custom TypeNameHandling = TypeNameHandling.Objects is used to initialize the JsonSerializerSettings. Anyway this will lead to an exception in https://github.com/EasyNetQ/EasyNetQ/blob/master/Source/EasyNetQ/RabbitAdvancedBus.cs, line 636, at the type comparison.

Stack trace example Newtonsoft.Json.JsonSerializationExceptio n: Could not create an instance of type *****************. Type is an interface or abstract class and cannot be instantiated. Path ***, line 1, position 41. at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateNewObject(JsonReader reader, JsonObjectContract objectContract, JsonProperty con tainerMember, JsonProperty containerProperty, String id, Boolean& createdFromNonDefaultCreator) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty m ember, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonPro perty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent) at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType) at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings) at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings) at EasyNetQ.DefaultMessageSerializationStrategy.DeserializeMessage[T](MessageProperties properties, Byte[] body) at EasyNetQ.RabbitAdvancedBus.Get[T](IQueue queue)

Setup EasyNetQ 0.50.7.399 Json.NET 6.0.7

Reproduction

See following test case (unfortunately attachment type is not supported). First test passes, second test throws the exception.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using EasyNetQ;
using EasyNetQ.Topology;
using NUnit.Framework;


namespace Common.Tests.Messages
{

    public interface TestInterface
    {

    }

    public class TestClass : TestInterface
    {
        public TestClass()
        {
            Test = 50;
        }

        public int Test { get; set; }
    }

    public class EasyNetQFailureExample
    {

        private IAdvancedBus bus;
        private IQueue queue;
        private IExchange exchange;

        private string key = "testqueue";

        [SetUp]
        public void SetUp()
        {
            string rabbitConnString = String.Format("host={0};virtualHost={1};username={2};password={3};prefetchcount=1",
               "localhost", "/", "guest", "guest");
            var rabbitBus = RabbitHutch.CreateBus(rabbitConnString);
            bus = rabbitBus.Advanced;
            exchange = bus.ExchangeDeclare("testExchange", ExchangeType.Direct, durable: false);
            queue = bus.QueueDeclare(key, durable: false, maxPriority: 10);
            bus.Bind(exchange, queue, key);
        }

        [TearDown]
        public void TearDown()
        {
            bus.Dispose();
        }

        [Test]
        public void TestConsume()
        {
            Action<IMessage<TestInterface>, MessageReceivedInfo> testAction =
                (message, info) => Console.WriteLine(message.Body.GetType());
            bus.Consume(queue, testAction);
            IMessage<TestInterface> msg = new Message<TestInterface>(new TestClass());
            bus.Publish(exchange, key, true, false, msg);
        }

        [Test]
        public void TestGet()
        {
            IMessage<TestInterface> msg = new Message<TestInterface>(new TestClass());
            bus.Publish(exchange, key, true, false, msg);
            IBasicGetResult<TestInterface> result = bus.Get<TestInterface>(queue);
            if (result.MessageAvailable)
            {
                Console.WriteLine(result.Message.Body.GetType());
            }
            else
            {
                Console.WriteLine("No message available");
            }
        }

    }
}

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:1
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
ldenardocommented, Dec 3, 2015

A workaround exploiting deserialization code for IMessage:

[Test]
        public void TestGetManualSerialization()
        {
            IMessage<TestInterface> msg = new Message<TestInterface>(new TestClass());
            bus.Publish(exchange, key, true, false, msg);
            IBasicGetResult result = bus.Get(queue);
            var mss = bus.Container.Resolve<IMessageSerializationStrategy>();
            IMessage message = mss.DeserializeMessage(result.Properties, result.Body);
            TestInterface deserialized = message.GetBody() as TestInterface;
            Console.WriteLine((deserialized as TestClass).Test);
        }
0reactions
Plinercommented, May 17, 2018

@ldenardo Actually, your workaround is exactly what we need to fix this issue.

screen shot 2018-05-17 at 09 47 24

The behaviour of jsonserializer is actually described here. So, the fix is to pass Type to serializer explicitly.

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - Getting Serializable Error Even After Inserting ...
When serializing the list of objects of type infoCategories - all properties of these objects are serialized. So is the img property, ...
Read more >
C# (CSharp) IAdvancedBus Examples
These are the top rated real world C# (CSharp) examples of IAdvancedBus ... throw new ArgumentNullException(nameof(messageSerializationStrategy)); }.
Read more >
Serialization and error queue filling issue
Hi,. I am using Mass Transit with RabbitMQ, using binary serialization. ... System.Runtime.Serialization.SerializationException: A JSON ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found