C# NServiceBus序列化问题-不';似乎不尊重序列化程序配置

C# NServiceBus序列化问题-不';似乎不尊重序列化程序配置,c#,serialization,nservicebus,C#,Serialization,Nservicebus,所以我开始在NServiceBus上遇到这个问题,它显然会接受消息并序列化它们,但似乎无法对它们进行反序列化以进行处理。我尝试过用几种不同的方式设置序列化程序。下面是我从错误队列中提取的一些异常(堆栈顶部) //未设置序列化程序。似乎NServiceBus序列化为 XML(如文档所示),但尝试使用NewtonSoft进行反序列化 “NServiceBus.ExceptionInfo.StackTrace”: “NServiceBus.MessageDeserializationException

所以我开始在NServiceBus上遇到这个问题,它显然会接受消息并序列化它们,但似乎无法对它们进行反序列化以进行处理。我尝试过用几种不同的方式设置序列化程序。下面是我从错误队列中提取的一些异常(堆栈顶部)

//未设置序列化程序。似乎NServiceBus序列化为 XML(如文档所示),但尝试使用NewtonSoft进行反序列化

“NServiceBus.ExceptionInfo.StackTrace”: “NServiceBus.MessageDeserializationException:运行时出错 正在尝试从传输消息中提取逻辑消息 7cc546df-09ca-493e-bb6d-a6ce00a6bb10---> Newtonsoft.Json.JsonReaderException:遇到意外字符 分析值时:System.Exception:无法 查找“Newtonsoft.Json.Linq.JObject”的元数据。\u000d\u000a确保 以下内容:\u000d\u000a1。“Newtonsoft.Json.Linq.JObject”是 包含在初始扫描中。\u000d\u000a2。 'Newtonsoft.Json.Linq.JObject'实现'IMessage','IEvent' 或者“ICommand”,或者,如果您不想实现 接口,您可以使用“不引人注目的模式”。\u000d\u000a NServiceBus.Unicast.Messages.MessageMetadataRegistry.GetMessageMetadata(类型 消息类型)在

这感觉像是两件事中的一件或全部。根据我所看到的,我的想法是:

  • 出于某种原因,当我设置json序列化程序时,对象正在使用相同的方法进行序列化(不确定是什么)
  • 不管我设置了什么序列化程序(或者即使我通过向反序列化程序添加相同的序列化程序来镜像),它都会尝试使用Newtonsoft对其进行反序列化
我认为其他几点可能有用:

  • 从消息中包含的标题(从错误队列):
    • 使用任一json序列化程序时,内容类型为application/json,内部异常为Newtonsoft.json.JsonReaderException
    • 如果不设置序列化程序,则内容类型为text/xml,内部异常为Newtonsoft.Json.JsonReaderException
  • 这是在WebAPI应用程序中托管的
    • 也许这会影响序列化程序的选择
  • 消息类在一个共享的pcl库中。我没有实现IMessage(etc)接口,而是在配置期间将它们包含在约定中(不引人注目的模式)
  • 这在一段时间内运行良好,但本周刚刚开始抛出这些错误。我找不到任何与NServiceBus相关的我已更改的内容
  • 我以前对命令有这个问题,但是当我为NServiceBus添加Newtonsoft nuget库时,命令(Send())停止抛出这个错误。但是现在事件(Publish())仍然抛出相同的异常
  • 我在另一个线程中看到,有人建议查看消息中的json主体,看看序列化主体是否有$type属性,但事实并非如此
任何洞察都会有帮助。为什么序列化程序没有排队

以下是一些杂项信息:

配置:

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);
}

事实证明,问题似乎在于下游订阅服务器上的消息版本较旧。对象相同,但在构建服务器上的每个构建上都会更新程序集版本,然后推送到Nuget(例如1.0.0.45621)。据推测,只要主要修订没有更改,并且NServiceBus仍然可以在指定的命名空间中找到名称为的对象,那么NServiceBus就不应该有问题。显然,这有一些细微差别,因为只要我更新了另一个组件中的库,错误就停止了

我从这条线索中得到了这个想法

其中一位开发人员特别提到NSB需要避免在标题中使用FQAN。我查看了错误中包含的消息标题,注意到源代码是我正在使用的服务,所附消息类型的FQAN显示的修订号与错误中使用的修订号不同在服务中。所以我打开了车上目前唯一的其他服务,发现一个匹配。我更新了它,一切都很好


我关注了这里提到的问题,但它似乎关闭了它,代替了我没有完全理解的其他东西。无论如何,这是我的解决方案。我仍在寻求澄清,或者我将与他们开罚单,因为这在未来是不可持续的。开发人员将不断在共享库中工作,我们无法在平台上的每个微服务中更新库(短时间内将超过20个)每次进行更改。

事实证明,问题似乎在于下游订阅服务器上的消息版本较旧。对象是相同的,但程序集版本在构建服务器上的每个构建上都会更新,然后推送到Nuget(例如1.0.0.45621)。据推测,只要主要修订没有更改,并且NServiceBus仍然可以在指定的命名空间中找到名称为的对象,那么NServiceBus就不应该有问题。显然,这有一些细微差别,因为只要我更新了另一个组件中的库,错误就停止了

我从这条线索中得到了这个想法

其中一位开发人员特别提到NSB需要避免在标题中使用FQAN。我查看了错误中包含的消息标题,注意到源代码是我正在使用的服务,所附消息类型的FQAN显示的修订号与错误中使用的修订号不同在服务中。所以我打开了车上目前唯一的其他服务,发现一个匹配。我更新了它,一切都很好

我关注了上面提到的问题,但看起来
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);
}