【问题标题】:Automatically adding headers to Rebus messages自动向 Rebus 消息添加标头
【发布时间】:2013-11-22 10:06:28
【问题描述】:

配置 Rebus 总线时,您可以指定它应该查找 Headers.UserName 标头,如 here 所述。这允许您使用正确的用户名自动填充Thread.CurrentPrincipal。这很好用,但我想知道是否有一种以标准方式设置标题的好方法,而不是在发送每条消息时手动设置它。

我正在构建一个基于 ASP.NET Web API 的服务,并且希望每个请求都将标头设置为在 apiControllerInstance.RequestContext.Principal.Identity.Name 中找到的名称。

一个不错的解决方案是在可以访问消息总线的基础 ApiController 上创建一个方法,因此您可以执行以下操作:

public IHttpActionResult SomeAction(SomeMessage message)
{
    SendWithUser(message);
    return Ok();
}

问题是你必须记住这样做,所以我想得到一些关于如何以更一般的方式做到这一点的建议。此外,其他标头可能会在未来变得相关,这也会对这种方法产生问题。

更新

根据 mookid 的回答,我提出了以下解决方案(我刚刚验证它适用于我的一个请求,但我不承诺稳健性):

public static void SetUserNameHeaderWhenCurrentPrincipalIsPresent(this IRebusEvents events)
{
    events.MessageSent += (bus, destination, message) =>
    {
        if (HttpContext.Current.User != null && !string.IsNullOrWhiteSpace(HttpContext.Current.User.Identity.Name))
            bus.AttachHeader(message, Headers.UserName, HttpContext.Current.User.Identity.Name);
    };
}

用法:

.Events(e => e.SetUserNameHeaderWhenCurrentPrincipalIsPresent())

【问题讨论】:

    标签: c# asp.net-web-api rebus


    【解决方案1】:

    你可以使用

    Configure.With(...)
        .(...)
        .Events(e => e.MessageSent += SetUsername)
    

    为每条传出消息调用SetUsername,您可以在此处查找HttpContext.Current

    如果您认为缺少其他内容,请告诉我这对您有何影响:)

    【讨论】:

    • Rebus新版本没有Events配置方法,Rebus新版本如何给事件添加自定义事件处理函数?
    • 是否可以使用 autofac 将“HttpContext.Current”转换为“HttpRequestMessage”?我需要支持自托管环境。
    • 有一个Rebus.Events 包用于较新版本的 Rebus! (对不起,迟到的答案:))
    【解决方案2】:

    尝试将装饰器模式与 autofac 结合使用。以下示例说明了一种可能的解决方案:

    public class RebusConfig  {
    
        protected override void Load(ContainerBuilder builder)
        {
            //Autofac configuration to decorate Rebus
            builder.RegisterDecorator<IBus>(
                        (c, inner) => new RebusMetadataDecorator(
                                inner, c.Resolve<HttpRequestMessage>()),
                        fromKey: "Metadata")
                         .InstancePerRequest();
    
        }
    
        public override SetContainer(IContainer container){
                //Configure the desired rebus
                var bus = Rebus.Config.Configure.With(new AutofacContainerAdapter(container));
    
                //Reconfigure rebus to support decorator
                //Note: I want to improve this step!
                var containerUpdate = new ContainerBuilder();
    
                containerUpdate
                      .RegisterInstance(bus)
                      .SingleInstance()
                      .Named<IBus>("Metadata");
    
                containerUpdate.Update(container);
         }          
    }           
    
    //Rebus Decorator               
    public class RebusMetadataDecorator : IBus
    {
            private  HttpRequestMessage requestMessage;
            private  IBus bus;
    
            public RebusMetadataDecorator(
                IBus bus, HttpRequestMessage requestMessage)
            {
                this.requestMessage = requestMessage;
                this.bus = bus;
            }
    
            public void Publish<TEvent>(TEvent message)
            {
                SetHttpMetadataToHeader(bus, message, metadataProvider, prefix);
                bus.Publish<TEvent>(message);
            }
    }
    

    【讨论】:

      【解决方案3】:

      标头可以很好地添加到发送消息中。下面的例子。

      private readonly IBus messageBus;
      ...
      var expirationHeader = new Dictionary<string, string>
      {
          { Headers.TimeToBeReceived, "00:00:30" },
      };
      
      this.messageBus.Send(reqMsg, expirationHeader).ConfigureAwait(false);
      

      【讨论】:

      • 您能否提供书面解释来补充您提供的代码?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-08-15
      • 1970-01-01
      • 1970-01-01
      • 2012-03-19
      • 1970-01-01
      • 1970-01-01
      • 2015-06-17
      相关资源
      最近更新 更多