EasyNetQ deserialize: why does my message not succeed and typeName is "null"?

548 Views Asked by At

I have a repository which is a message Consumer, working with RabbitMQ and using the ITypeNameSerializer to map received messages on the queue, to known types that we can process.

First I'll show some code:

I have a custom serializer class:

internal class AcceptedTypeNameSerializer : ITypeNameSerializer
{
    private static readonly ConcurrentDictionary<string, Type> AcceptedTypes = new ConcurrentDictionary<string, Type>
    {
        ["SomeType"] = typeof(SomeType),
        ["AnotherType"] = typeof(AnotherType),
    };

    private readonly ITypeNameSerializer _defaultTypeNameSerializer;

    public AcceptedTypeNameSerializer(ITypeNameSerializer defaultTypeNameSerializer)
    {
        _defaultTypeNameSerializer = defaultTypeNameSerializer;
    }

    public string Serialize(Type type) => _defaultTypeNameSerializer.Serialize(type);

    public Type DeSerialize(string typeName) =>
        AcceptedTypes.TryGetValue(typeName, out var type)
            ? type
            : _defaultTypeNameSerializer.DeSerialize(typeName);
}

In ApplicationModule this is registered as such:

private static IBus CreateBus(string connectionString) =>
        RabbitHutch.CreateBus(connectionString,
            serviceRegister =>
            {
                serviceRegister.Register<ISerializer>(resolver =>
                    new JsonSerializer(new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.None }));
                serviceRegister.Register<ITypeNameSerializer>(resolver =>
                    new AcceptedTypeNameSerializer(new DefaultTypeNameSerializer()));
                serviceRegister.Register<IConventions, QueueConventions>();
            });

When sending the following message to the queue, it gets picked up by this Consumer but when it hits the "Deserialize" part of the code, "typeName" is "null" and I can't seem to find an example online where it's specified where this "typeName" string comes from & what I need to change in my message to make it work.

Here's (part of) the message:

{
  "Brand": "string",
  "Id": int,
  "State": "Confirmed",
  "Validations": {
    [
      ...
    ]
  },
  "TrackerData": null,
  "Type": "acquisition",
  "Language": "en",
  "UniqueMessageId": "guid"
}

Whenever this message is sent, it should map to "SomeType" which has the following properties:

public string Brand { get; set; }
public string State { get; set; }
public IEnumerable<SomeValidationType> Validations { get; set; }

Can someone please explain where the "typeName" in the function "Deserialize" come from, why it's "null" in my case (see above message), and what I can do to fix it? I've tried passing a JSON property "type" or "typeName" but the value was always "null" so the code doesn't work.

It's a .NET Core core 3.1 application and uses EasyNetQ package version 6.3.1

1

There are 1 best solutions below

0
Tempuslight On

Ok so I finally found the issue... It's not with EasyNetQ but with RabbitMQ (or with myself rather).

What I tried todo was paste messageBody's from errormessages into the "normal" test queue, and it would always fail. That's because in our case, with the ITypeNameSerializer and multiple Event types, you also have to pass the "type" property with each message body! I didn't know about this ...

Like so:

RabbitMQ example