We are encountering an issue when sending messages to the
bus within a Web application (Asp.net, MVC, SignalR). Whenever we make a call to
the Bus.Send we encounter the above exception. I believe it might be related to the use
of Thread.CurrentPrincipal.Identity.Name within
the WindowsIdentityEnricher class.
namespace NServiceBus.Impersonation.Windows
{
using System.Threading;
using MessageMutator;
/// <summary>
/// Stamps outgoing messages with the current windows identity
/// </summary>
public class WindowsIdentityEnricher : IMutateOutgoingTransportMessages
{
void IMutateOutgoingTransportMessages.MutateOutgoing(object[] messages, TransportMessage transportMessage)
{
transportMessage.Headers[Headers.WindowsIdentityName] = Thread.CurrentPrincipal.Identity.Name;
}
}
}
It appears to be linked to an issue identified here, in which the identity of the user is bound to each request and the Thread.CurrentPrincipal is null.
My questions are:
12. Is this IIS closing the identity between the requests? Should the above code in the WindowsIdentityEnricher be wrapped within an exception?
2. Are there any methods can disable certain message mutators? Is the windows identity a requirement for messages or is it merely used for logging purposes?
3. Given my implementation below. Is it a safe implementation? Are there any obvious gotchas? (reduced for clarity)
private static IBus bus;
protected static IBus Bus
{
get
{
if (bus == null)
{
Init(Endpoint);
}
return bus;
}
}
CALLED WITHIN Globala.asax Application Start
public static void Init()
{
if (bus != null)
return;
lock (typeof(ServiceBus))
{
if (bus != null)
return;
bus = Configure.With()
.DefineEndpointName(EndpointName)
.DoNotCreateQueues()
.StructureMapBuilder()
.UseTransport<SqlServer>(ConnectionStringName)
.PurgeOnStartup(false)
.UnicastBus()
.CreateBus()
.Start(() => Configure.Instance.ForInstallationOn<Windows>().Install());
}
}
public static void SendMessage(Command cmd)
{
Send(cmd);
}
private static void Send(object cmd)
{
try
{
Bus.Send(cmd); EXCEPTION OCCURS HERE
}
catch (Exception e)
{
// exception handling here
}
}
}
Product name:
NServiceBus
Version:
4.4.0
Exception:
ObjectDisposedException
Message:
Safe handle has been closed
Stacktrace:
at System.Runtime.InteropServices.SafeHandle.DangerousAddRef(Boolean& success) at System.StubHelpers.StubHelpers.SafeHandleAddRef(SafeHandle pHandle, Boolean& success) at Microsoft.Win32.Win32Native.GetTokenInformation(SafeTokenHandle TokenHandle, UInt32 TokenInformationClass, SafeLocalAllocHandle TokenInformation, UInt32 TokenInformationLength, UInt32& ReturnLength) at System.Security.Principal.WindowsIdentity.GetTokenInformation(SafeTokenHandle tokenHandle, TokenInformationClass tokenInformationClass) at System.Security.Principal.WindowsIdentity.get_User() at System.Security.Principal.WindowsIdentity.GetName() at System.Security.Principal.WindowsIdentity.get_Name() at NServiceBus.Impersonation.Windows.WindowsIdentityEnricher.NServiceBus.MessageMutator.IMutateOutgoingTransportMessages.MutateOutgoing(Object[] messages, TransportMessage transportMessage) in \src\NServiceBus.Core\Impersonation\Windows\WindowsIdentityEnricher.cs:line 13 at NServiceBus.MessageMutator.MutateOutgoingPhysicalMessageBehavior.Invoke(SendPhysicalMessageContext context, Action next) in \src\NServiceBus.Core\MessageMutator\MutateOutgoingPhysicalMessageBehavior.cs:line 20 at NServiceBus.Pipeline.BehaviorChain`1.InvokeNext(T context) in \src\NServiceBus.Core\Pipeline\BehaviorChain.cs:line 38 at NServiceBus.Pipeline.BehaviorChain`1.<>c__DisplayClass1.<InvokeNext>b__0() in \src\NServiceBus.Core\Pipeline\BehaviorChain.cs:line 38 at NServiceBus.Unicast.Behaviors.SerializeMessagesBehavior.Invoke(SendPhysicalMessageContext context, Action next) in \src\NServiceBus.Core\Unicast\Behaviors\SerializeMessagesBehavior.cs:line 43 at NServiceBus.Pipeline.BehaviorChain`1.InvokeNext(T context) in \src\NServiceBus.Core\Pipeline\BehaviorChain.cs:line 38 at NServiceBus.Pipeline.PipelineExecutor.Execute[T](BehaviorChain`1 pipelineAction, T context) in \src\NServiceBus.Core\Pipeline\PipelineExecutor.cs:line 137 at NServiceBus.Pipeline.PipelineExecutor.InvokeSendPipeline(SendOptions sendOptions, TransportMessage physicalMessage) in \src\NServiceBus.Core\Pipeline\PipelineExecutor.cs:line 101 at NServiceBus.Unicast.Behaviors.CreatePhysicalMessageBehavior.Invoke(SendLogicalMessagesContext context, Action next) in \src\NServiceBus.Core\Unicast\Behaviors\CreatePhysicalMessageBehavior.cs:line 53 at NServiceBus.Pipeline.BehaviorChain`1.InvokeNext(T context) in \src\NServiceBus.Core\Pipeline\BehaviorChain.cs:line 38 at NServiceBus.Pipeline.BehaviorChain`1.<>c__DisplayClass1.<InvokeNext>b__0() in \src\NServiceBus.Core\Pipeline\BehaviorChain.cs:line 38 at NServiceBus.Unicast.Behaviors.MultiMessageBehavior.Invoke(SendLogicalMessagesContext context, Action next) in\src\NServiceBus.Core\Unicast\Behaviors\MultiMessageBehavior.cs:line 21 at NServiceBus.Pipeline.BehaviorChain`1.InvokeNext(T context) in \src\NServiceBus.Core\Pipeline\BehaviorChain.cs:line 38 at NServiceBus.Pipeline.BehaviorChain`1.<>c__DisplayClass1.<InvokeNext>b__0() in \src\NServiceBus.Core\Pipeline\BehaviorChain.cs:line 38 at NServiceBus.Unicast.Behaviors.MultiSendValidatorBehavior.Invoke(SendLogicalMessagesContext context, Action next) in \src\NServiceBus.Core\Unicast\Behaviors\MultiSendValidatorBehavior.cs:line 36 at NServiceBus.Pipeline.BehaviorChain`1.InvokeNext(T context) in \src\NServiceBus.Core\Pipeline\BehaviorChain.cs:line 38 at NServiceBus.Pipeline.PipelineExecutor.Execute[T](BehaviorChain`1 pipelineAction, T context) in \src\NServiceBus.Core\Pipeline\PipelineExecutor.cs:line 137 at NServiceBus.Pipeline.PipelineExecutor.InvokeSendPipeline(SendOptions sendOptions, IEnumerable`1 messages) in \src\NServiceBus.Core\Pipeline\PipelineExecutor.cs:line 79 at NServiceBus.Unicast.UnicastBus.InvokeSendPipeline(SendOptions sendOptions, List`1 messages) in \src\NServiceBus.Core\Unicast\UnicastBus.cs:line 744 at NServiceBus.Unicast.UnicastBus.SendMessages(SendOptions sendOptions, List`1 messages) in \src\NServiceBus.Core\Unicast\UnicastBus.cs:line 725 at NServiceBus.Unicast.UnicastBus.Send(Object[] messages) in \src\NServiceBus.Core\Unicast\UnicastBus.cs:line 571 at NServiceBus.Unicast.UnicastBus.Send(Object message) in \src\NServiceBus.Core\Unicast\UnicastBus.cs:line 555 at XXXXXX.Send(Object cmd)
Things I've tried:
I have tried overriding the DependencyLifecycle to InstancePerCall for the WindowsIdentityEnricher but to no avail.
I have experimented with the ImpersonateSender method when instantiating the Bus as well.
Considerations:
I thought I'd created a forum post already but I can't seem to find it... so apologies if this creates a double post.
Thanks
/// <summary> /// Stamps outgoing messages with the current windows identity /// </summary> public class WindowsIdentityEnricher : IMutateOutgoingTransportMessages { void IMutateOutgoingTransportMessages.MutateOutgoing(object[] messages, TransportMessage
transportMessage) { transportMessage.Headers[Headers.WindowsIdentityName] = GetWindowsIdentityName(); } private string GetWindowsIdentityName() { var identityName = string.Empty; var currentIdentity = WindowsIdentity.GetCurrent(); if (currentIdentity != null) { identityName = currentIdentity.Name; } return identityName; } }