修改传出NServiceBus订阅消息的标头以将信息传递给IAuthorizeSubscriptions

时间:2014-06-18 08:40:20

标签: nservicebus

我正在使用NServiceBus 4.4.2,我创建了一个实现IAuthorizeSubscriptions的类,以接受/拒绝订阅。我需要在发布者中提供有关订阅者的一些其他信息,因此我尝试创建一个实现IMutateOutgoingTransportMessages的类,并使用ConfigureComponent<MyMutator>(DependencyLifecycle.InstancePerCall)以正常方式注册它。所有这个类都是为传出消息添加标题。

不幸的是,订阅者发送订阅控制消息时未设置标头。我已经检查过,如果订阅者做了一个Bus.Send(),我的自定义标题 被附加到传输消息的Headers集合中,所以我不认为这是我的mutator的问题,除非我需要以不同方式注册。

有没有办法将标题添加到订阅消息中,或者我是否采用了错误的方式并且应该通过其他方式传递信息?

修改

Mutator Code:

public class MyMutator : IMutateOutgoingTransportMessages
{
    public void MutateOutgoing(object[] messages, TransportMessage transportMessage)
    {
        transportMessage.Headers.Add("CustomHeader", "Test");
    }
}

IAuthorizeSubscriptions代码:

我可以在AuthorizeSubscribe方法中设置一个断点,但它会被点击,但headers不包含我的自定义标题。

public class SubscriptionAuthoriser : IAuthorizeSubscriptions
{
    public bool AuthorizeSubscribe(string messageType, string clientEndpoint, IDictionary<string, string> headers)
    {
        // headers doesn't contain the "CustomHeader" header

        return true;
    }

    public bool AuthorizeUnsubscribe(string messageType, string clientEndpoint, IDictionary<string, string> headers)
    {
        return true;
    }
}

1 个答案:

答案 0 :(得分:0)

从NServiceBus版本4.3开始,不再调用传出订阅消息调用InvokeOutgoingTransportMessagesMutators,因此消息标题不再可能出现这种情况。我问了一段类似的问题@ https://groups.google.com/forum/#!topic/particularsoftware/XVLQkCouKCk。当我在等待上述线程的响应时,我实现了一个临时解决方法,这是一种手动订阅方法(主要使用NServiceBus单播总线源构建)。这可能不是推荐的,但我想我会发布它,无论如何它会帮助某人。

public void Subscribe(Type eventType, Address targetAddress)
{
    var transportMessage = new TransportMessage
        {
            ReplyToAddress = Address.PublicReturnAddress,
            Recoverable = true
        };
        transportMessage.Headers.Add("NServiceBus.ControlMessage", true.ToString());
        transportMessage.Headers["SubscriptionMessageType"] = eventType.AssemblyQualifiedName;
        transportMessage.MessageIntent = MessageIntentEnum.Subscribe;

        var fdqn = OutgoingTransportMessageMutator.GetLocalhostFqdn();
        transportMessage.ReplyToAddress = new Address(transportMessage.ReplyToAddress.Queue, fdqn);

        string fullPath = MsmqUtilities.GetFullPath(targetAddress);
        try
        {
            using (var messageQueue = new MessageQueue(fullPath, false, false, QueueAccessMode.Send))
            {
                using (var message1 = MsmqUtilities.Convert(transportMessage))
                {
                    message1.UseDeadLetterQueue = false;
                    message1.UseJournalQueue = false;
                    message1.ResponseQueue = new MessageQueue(MsmqUtilities.GetReturnAddress(transportMessage.ReplyToAddress.ToString(), targetAddress.ToString()));
                    messageQueue.Send(message1, MessageQueueTransactionType.Single);
                }
            }
        }
        catch (MessageQueueException ex)
        {
            if (ex.MessageQueueErrorCode == MessageQueueErrorCode.QueueNotFound)
            {
                string message1 = targetAddress == (Address)null ? "Failed to send message. Target address is null." : string.Format("Failed to send message to address: [{0}]", targetAddress);
                throw new QueueNotFoundException(targetAddress, message1, ex);
            }
            throw;
        }
        catch (Exception ex)
        {
            _log.Error(ex);
            throw;
         }
     }