C# 自动向Rebus消息添加标题

C# 自动向Rebus消息添加标题,c#,asp.net-web-api,rebus,C#,Asp.net Web Api,Rebus,配置Rebus总线时,您可以指定它应查找头文件。UserName头文件,如下所述。这允许您使用正确的用户名自动填充线程.CurrentPrincipal。这非常有效,但我想知道是否有一种好方法可以以标准方式设置标题,而不是在发送每条消息时手动设置标题 我正在构建一个基于ASP.NET Web API的服务,希望每个请求都将头设置为在apiControllerInstance.RequestContext.Principal.Identity.name中找到的名称 一个不错的解决方案是在基本Api

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

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

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

public IHttpActionResult SomeAction(SomeMessage message)
{
    SendWithUser(message);
    return Ok();
}
问题是你必须记住要这样做,所以我想得到一些关于如何以更普遍的方式这样做的建议。此外,其他标题将来可能会变得相关,这也会对这种方法产生问题

更新 根据mookid的回答,我提出了以下解决方案(我刚刚验证了它适用于我的一个请求,但我没有就健壮性做出任何承诺):

用法:

.Events(e => e.SetUserNameHeaderWhenCurrentPrincipalIsPresent())
你可以用

Configure.With(...)
    .(...)
    .Events(e => e.MessageSent += SetUsername)
要为每个传出消息调用
SetUsername
,您可以在
HttpContext.Current


请让我知道这对您的效果如何,或者如果您认为缺少其他内容:)

尝试使用装饰图案与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);
        }
}
公共类重新配置{
受保护的覆盖无效负载(ContainerBuilder builder)
{
//Autofac配置用于装饰Rebus
builder.RegisterDecorator(
(c,内部)=>新的重新安装数据装饰器(
内部,c.Resolve()),
fromKey:“元数据”)
.InstancePerRequest();
}
公共覆盖设置容器(IContainer容器){
//配置所需的REBU
var bus=Rebus.Config.Configure.With(新的AutofacContainerAdapter(容器));
//重新配置rebus以支持decorator
//注意:我想改进这一步!
var containerUpdate=new ContainerBuilder();
容器更新
.RegisterInstance(总线)
.SingleInstance()
.命名为(“元数据”);
containerUpdate.Update(容器);
}          
}           
//装饰工
公共类重新构建数据装饰器:IBus
{
私有HttpRequestMessage请求消息;
私人IBus巴士;
公共重建数据装饰器(
IBus总线,HttpRequestMessage(请求消息)
{
this.requestMessage=requestMessage;
这辆公共汽车=公共汽车;
}
公共无效发布(TEvent消息)
{
SetHttpMetadataToHeader(总线、消息、metadataProvider、前缀);
发布(消息);
}
}

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

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

this.messageBus.Send(reqMsg, expirationHeader).ConfigureAwait(false);
专用只读IBus消息总线;
...
var expirationHeader=新字典
{
{Headers.TimeToBeReceived,“00:00:30”},
};
this.messageBus.Send(reqMsg,expirationHeader).configureWait(false);

更新版本的Rebus中没有事件配置方法,如何向更新版本的Rebus中的事件添加自定义事件处理程序?是否可以使用autofac将“HttpContext.Current”转换为“HttpRequestMessage”?我需要支持自托管环境。有一个包用于更新版本的Rebus!(很抱歉回答得太晚:))你能提供一个书面解释来补充你提供的代码吗?
private readonly IBus messageBus;
...
var expirationHeader = new Dictionary<string, string>
{
    { Headers.TimeToBeReceived, "00:00:30" },
};

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