Reputation: 41
I'm building a webapplication that contains an internal self-hosted WCF service with Named Pipes endpoint. This works great, except whenever I want to host this webapplication on IIS, using a shared UNC virtualpath ('\server\share') in combination with physicalpathcredentials. Whenever I attempt to run this situation, I get an error:
Error: System.ServiceModel.EndpointNotFoundException: 'There was no endpoint listening at net.pipe://localhost/futurama/pid4988/instance2 that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.'
AddressAccessDeniedException: The pipe name could not be obtained for net.pipe://localhost/futurama/pid4988/instance2.
PipeException: The pipe name could not be obtained for the pipe URI: Unrecognized error 5 (0x5)
Is suspect this is a credentials/rights-issue, but I cannot figure out how to fix it. Does anyone have an idea?
I've simplified the problem in a sample, and whenever I start this sample, the thread simply blocks, and the process uses 25% of my processor.
The Global.asax file:
public class Global : System.Web.HttpApplication
{
public static ClientProvider<ITestService> Provider { get; set; }
protected void Application_Start(object sender, EventArgs e)
{
Provider = new ClientProvider<ITestService>(typeof(TestService));
using (var client = Provider.GetClient())
{
string result = client.Proxy.SayHello("world");
// this is never reached :(
}
}
protected void Application_End(object sender, EventArgs e)
{
Provider.Dispose();
}
}
The internal service:
[ServiceContract]
public interface ITestService
{
[OperationContract]
string SayHello(string name);
}
public class TestService : ITestService
{
public string SayHello(string name)
{
return string.Format("Hello, {0}", name);
}
}
The selfhosting class:
public class ClientProvider<T> : IDisposable
{
protected ServiceHost ServiceHost { get; set; }
public string Address { get; protected set; } = "net.pipe://localhost/test/instance";
public ClientProvider(Type implementingType)
{
ServiceHost = new ServiceHost(implementingType);
System.ServiceModel.Channels.Binding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
ServiceHost.AddServiceEndpoint(typeof(T), binding, Address);
ServiceHost.Open();
}
internal Client<T> GetClient()
{
var client = new Client<T>(this, Address.ToString());
return client;
}
internal void Close()
{
ServiceHost.Close();
}
public void Dispose()
{
Close();
}
}
The client that provides a proxy:
public class Client<T> : IDisposable
{
public T Proxy { get; protected set; }
protected ChannelFactory<T> Factory { get; set; }
protected ClientProvider<T> Provider { get; set; }
internal Client(ClientProvider<T> provider, string address)
{
Provider = provider;
System.ServiceModel.Channels.Binding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
EndpointAddress endpointAddress = new EndpointAddress(address);
Factory = new ChannelFactory<T>(binding, endpointAddress);
Proxy = Factory.CreateChannel();
}
public void Dispose()
{
IClientChannel channel = Proxy as IClientChannel;
try { channel.Close(); }
catch { channel.Abort(); }
try { Factory.Close(); }
catch { Factory.Abort(); }
}
}
Does anyone know why IIS with a UNC virtual path messes this up?
Upvotes: 1
Views: 405
Reputation: 41
In the end, we fixed this problem bij setting a Impersonationcontext to temporarily undo any impersonation:
WindowsIdentity currentIdentity = WindowsIdentity.GetCurrent();
if (!currentIdentity.IsSystem && currentIdentity.ImpersonationLevel == TokenImpersonationLevel.Impersonation)
{
impersonationContext = WindowsIdentity.Impersonate(IntPtr.Zero); //revert to previous identity (apppool identity)
}
This seemed to solve our problems.
Upvotes: 1