So I started having this problem with NServiceBus where it'll apparently accept messages and serialize them, but can't seem to deserialize them for processing. I've tried setting the serializer in settings a few different ways. Here are some of the exceptions (top of the stack) that I pulled from the error queue.
// not setting the serializer. Appears that NServiceBus serializes as XML (as documented) but tries to deserialize using NewtonSoft
"NServiceBus.ExceptionInfo.StackTrace" : "NServiceBus.MessageDeserializationException: An error occurred while attempting to extract logical messages from transport message 7cc546df-09ca-493e-bb6d-a6ce00a6bb10 ---> Newtonsoft.Json.JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.\u000d\u000a at Newtonsoft.Json.JsonTextReader.ParseValue() in C:\Build\src\NServiceBus.Core\CircuitBreakers\CircuitBreaker.cs:line 0\u000d\u000a at NServiceBus.JsonMessageSerializer.Deserialize(Stream stream, IList`1 messageTypes) in C:\Build\src\NServiceBus.Core\Serializers\Json\JsonMessageSerializer.cs:line 108\u000d\u000a at ...
// with setting the serializer to the normal NServiceBus JsonSerializer (as in the tutorials). Looks like it can't deserialize JObject because it didn't include Newtonsoft in the scan. But why is it JObject at all?
"NServiceBus.ExceptionInfo.StackTrace" : "NServiceBus.MessageDeserializationException: An error occurred while attempting to extract logical messages from transport message ee5c8703-f509-40aa-a187-a6ce00a7fd1e ---> System.Exception: Could not find metadata for 'Newtonsoft.Json.Linq.JObject'.\u000d\u000aEnsure the following:\u000d\u000a1. 'Newtonsoft.Json.Linq.JObject' is included in initial scanning. \u000d\u000a2. 'Newtonsoft.Json.Linq.JObject' implements either 'IMessage', 'IEvent' or 'ICommand' or alternatively, if you don't want to implement an interface, you can use 'Unobtrusive Mode'.\u000d\u000a at NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(Type messageType) in ...
// with setting the serializer to NewtonSoftSerializer it appears to be the same error "NServiceBus.ExceptionInfo.StackTrace" : "NServiceBus.MessageDeserializationException: An error occurred while attempting to extract logical messages from transport message 603e07e7-7877-4d71-90b3-a6ce00a9370b ---> System.Exception: Could not find metadata for 'Newtonsoft.Json.Linq.JObject'.\u000d\u000aEnsure the following:\u000d\u000a1. 'Newtonsoft.Json.Linq.JObject' is included in initial scanning. \u000d\u000a2. 'Newtonsoft.Json.Linq.JObject' implements either 'IMessage', 'IEvent' or 'ICommand' or alternatively, if you don't want to implement an interface, you can use 'Unobtrusive Mode'.\u000d\u000a at NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(Type messageType) in ...
This feels like one of or all of a couple things. My thoughts based on what I'm seeing are:
- For some reason, when I set either json serializer, objects are being serialized using the same method (not sure what)
- Regardless of what serializer I set (or even if I mirror by adding the same serializer to deserializers), it tries to deserialize it using Newtonsoft
Other points I think could be useful:
- From the headers included in message (from the error queue):
- When I use either json serializer, the content type is application/json and the inner exception is Newtonsoft.Json.JsonReaderException
- When I don't set the serializer, the content type is text/xml and the inner exception is Newtonsoft.Json.JsonReaderException
- This is being hosted in a WebAPI application
- Maybe this is affecting serializer selection?
- The message classes are in a shared pcl library. Instead of implementing the IMessage (etc) interface, I've included them in the conventions during config (unobtrusive mode).
- This was working fine for a while and then just started throwing these errors this week. I can't find anything that I've changed that are in any way related to NServiceBus.
- I used to have this problem with Commands, but when I added the Newtonsoft nuget library for NServiceBus, commands (Send()) stopped throwing this error. However now events (Publish()) are still throwing the same exception
- I saw in a different thread, someone suggested looking at the json body in the message to see if the serialized body had a $type property. It does not.
Any insight would be helpful. Why aren't the serializers lining up?
Here are some miscellaneous bits:
Configuration:
public static void Initialize(
string endpointName,
string instanceDescriminator,
IWindsorContainer container)
{
_endpointConfiguration = new EndpointConfiguration(ServiceEndpoint.Surveys);
_endpointConfiguration.SendFailedMessagesTo("error");
_endpointConfiguration.MakeInstanceUniquelyAddressable(instanceDescriminator);
_endpointConfiguration.UseContainer<WindsorBuilder>(customizations =>
{
customizations.ExistingContainer(container);
});
_endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.Sagas>();
_endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.Subscriptions>();
_endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.Timeouts>();
_endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.Outbox>();
_endpointConfiguration.UsePersistence<NHibernatePersistence, StorageType.GatewayDeduplication>();
_endpointConfiguration.EnableOutbox();
_endpointConfiguration.UseTransport<SqlServerTransport>();
_endpointConfiguration.EnableInstallers();
NServiceBusConventions.SetDasConventions(_endpointConfiguration);
}
Conventions:
public static void SetDasConventions(EndpointConfiguration config)
{
var conventions = config.Conventions();
conventions.DefiningCommandsAs(type => type.Namespace != null && type.Namespace.StartsWith("DAS.Infrastructure.Messaging.Command"));
conventions.DefiningEventsAs(type => type.Namespace != null && type.Namespace.StartsWith("DAS.Infrastructure.Messaging.Event"));
conventions.DefiningMessagesAs(type =>
type.Namespace != null &&
(type.Namespace.StartsWith("DAS.Infrastructure.Messaging.Message") || type.Namespace.StartsWith("DAS.Infrastructure.Messaging")));
conventions.DefiningEncryptedPropertiesAs(property => property.Name.StartsWith("Encrypted"));
conventions.DefiningDataBusPropertiesAs(property => property.Name.EndsWith("DataBus"));
conventions.DefiningExpressMessagesAs(type => type.Name.EndsWith("Express"));
conventions.DefiningTimeToBeReceivedAs(type => type.Name.EndsWith("Expires") ? TimeSpan.FromSeconds(30) : TimeSpan.MaxValue);
}