2010-11-04 88 views
4

我在自己的进程中使用NServiceBus(所以而不是使用通用主机),我想有一个特定顺序消息的多个消息处理程序。对于通用主机,您将实现ISpecifyMessageHandlerOrdering,但我不知道如何在托管自己的NServiceBus过程时执行此操作,因为该接口在NServiceBus.Host.exe中定义,我无法找到另一种方法来执行此操作。NServiceBus:指定消息顺序

这样做的目的是用户身份验证:在调用实际的消息处理程序之前,我首先要验证消息的发件人,这将发生在另一个更通用的消息处理程序中。该消息将是包含加密的用户名和密码和/或会话ID的类型。这种类型将用于几乎所有发送到服务器的命令(除了我认为的所有登录信息外)。这是使用NServiceBus进行用户认证的好方法吗?

目前,它拿起第二个处理程序,但没有按照正确的顺序。

更新

至于建议由David我试图创建一个IMessageModuleCurrentMessageContext读取头对用户进行认证。

我遇到了一些问题,在这里:

  • 我第一次发送消息时,bus.CurrentMessageContextnull。每次之后,它都会正确填写,我可以阅读标题。
  • 当用户未通过身份验证时调用bus.DoNotContinueDispatchingCurrentMessageToHandlers不会停止调用消息处理程序。 bus.Return(errorCode)也没有。我还有其他方法可以做到吗?
+0

出于好奇,为什么你不能使用通用主机? – 2010-11-04 17:51:52

+0

要停止调用消息处理程序,我认为您需要抛出某种NotAuthenticatedException。 – 2010-11-04 18:19:16

回答

7

由于文档页面上的NServiceBus常见问题描述:

http://docs.particular.net/nservicebus/handlers/handler-ordering

如何指定在处理程序被调用的顺序?

如果你写你自己的主机:如果您使用的通用主机

public class EndpointConfig : IConfigureThisEndpoint, ISpecifyMessageHandlerOrdering 
{ 
    public void SpecifyOrder(Order order) 
    { 
      order.Specify(First<H1>.Then<H2>().AndThen<H3>().AndThen<H4>() //etc); 
    } 
} 

如果你只想指定单个处理器(您自己的主机)

NServiceBus.Configure.With() 
... 
.UnicastBus() 
     .LoadMessageHandlers(First<H1>.Then<H2>().AndThen<H3>().AndThen<H4>() //etc) 
... 

NServiceBus.Configure.With() 
    ... 
    .UnicastBus() 
      .LoadMessageHandlers<FIRST<YourHandler>>() 
    ... 

如果你只想指定单个处理器(与通用主机)

public class EndpointConfig : IConfigureThisEndpoint, ISpecifyMessageHandlerOrdering 
{ 
    public void SpecifyOrder(Order order) 
    { 
      order.Specify<FIRST<YourHandler>>(); 
    } 
} 
+0

非常好,我已经通过文档内容进行了搜索,但没有搜索到FAQ。请问您的意见是否是进行用户身份验证的最佳方式?正如我所看到的,我有三种选择:多个消息处理程序(这个问题是关于什么的),David提出的'IMessageModule'(给我一些麻烦)或Adam Fyles建议的包装器(我没有尝试过)。似乎多个处理程序有一些开销。 – JulianR 2010-11-04 19:24:16

+0

NServiceBus默认将线程的Windows标识设置为发送消息的域用户的身份 - 这称为模拟。一旦你有了,你可以根据这些数据进行认证。如果您正在寻找授权,那么请在发送邮件的标题中查看声明。 – 2010-11-04 20:34:33

+0

我看了一下源代码,看起来'First'类真的只是一个简洁的方式来构造'Type'的列表。我想自己做,并通过它,但我该怎么做? – 2013-03-01 14:19:34

3

您是否考虑过用于此目的的消息模块?

public interface IMessageModule 
{ 
    // Methods 
    void HandleBeginMessage(); 
    void HandleEndMessage(); 
    void HandleError(); 
} 

实现此接口为您提供了在每条消息之前和之后调用代码的要点。如果您注入一个IBus,您可以访问当前的消息上下文,并从那里检查标题并使用它来验证您的消息。

+0

嗨,我确实已经考虑过使用这个,但我没有想过访问当前的消息上下文。我会研究这个,谢谢! :) – keepitstupid 2010-11-04 14:14:09

+0

嘿,我尝试了你的建议,并走了很长的路,但不完全。请参阅我的编辑。 – keepitstupid 2010-11-04 17:20:35

+0

对不起,我无法与此帐户upvote。奇怪的是,你不能总是为自己的问题提供答案。 – keepitstupid 2010-11-04 17:26:26

4

另一种可能性是实现一个基本的消息处理程序类,它会根据您的身份验证检查有条件地跳过处理。

public abstract class MessageHandlerBase<T> : IMessageHandler<T> where T : IMessage 
{ 
    public abstract void HandleMessage(T message); 

    public void Handle(T message) 
    { 

     if (CredentialsValid(message)) 
      this.HandleMessage(message); 

    } 
} 
+0

创意,我喜欢:) – JulianR 2010-11-04 19:02:24