自动将标头添加到Rebus消息

时间:2013-11-22 10:06:28

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

配置Rebus总线时,您可以指定它应查找here所述的Headers.UserName标头。这允许您使用正确的用户名自动填充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())

3 个答案:

答案 0 :(得分:2)

您可以使用

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

SetUsername调用每个外发邮件,这就是您可以在HttpContext.Current

上查找的地方

如果你认为缺少其他东西,请告诉我你的工作原理:)

答案 1 :(得分:0)

尝试使用与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);
        }
}

答案 2 :(得分:0)

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

private readonly IBus messageBus;
...
var expirationHeader = new Dictionary<string, string>
{
    { Headers.TimeToBeReceived, "00:00:30" },
};

this.messageBus.Send(reqMsg, expirationHeader).ConfigureAwait(false);