C# 自动向Rebus消息添加标题
配置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
头文件。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);