使用IErrorHandler和TCP信息安全造成超时 [英] Using IErrorHandler and TCP Message Security causes a timeout
问题描述
我有一个自定义的IServiceBehavior接口WCF服务连着用于返回特定的错误在客户端上。当我启用此code与TCP信息安全,我收到一个服务超时。
I have a WCF service with a custom IServiceBehavior attached used to return a specific fault on the client side. When I enable this code with TCP Message Security I receive a service timeout.
下面你可以看到完整的客户端和服务器code重现错误。
Below you can see the full client and server code to reproduce the error.
服务器code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
using System.ServiceModel.Channels;
namespace TestWCFServer
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("SERVER");
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.Message; //If you remove this line the code works!!!!
Uri address = new Uri("net.tcp://localhost:8184/");
// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(HelloWorldService)))
{
host.AddServiceEndpoint(typeof(IHelloWorldService), binding, address);
host.Description.Behaviors.Add(new MyErrorhandlerBehavior());
host.Open();
Console.WriteLine("The service is ready at {0}", address);
Console.WriteLine("Press to stop the service.");
Console.ReadLine();
// Close the ServiceHost.
host.Close();
}
}
}
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
string SayHello(string name);
}
public class HelloWorldService : IHelloWorldService
{
public string SayHello(string name)
{
if (name == null)
throw new ArgumentNullException("name");
return string.Format("Hello, {0}", name);
}
}
class MyErrorhandlerBehavior : IServiceBehavior, IErrorHandler
{
#region IServiceBahvior
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcher chanDisp in serviceHostBase.ChannelDispatchers)
{
chanDisp.ErrorHandlers.Add(this);
}
}
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
#endregion
#region IErrorHandler Members
public bool HandleError(Exception error)
{
return true;
}
public void ProvideFault(Exception error,MessageVersion ver, ref Message msg)
{
FaultException fe = new FaultException(error.Message);
MessageFault fault = fe.CreateMessageFault();
msg = Message.CreateMessage(ver, fault, "net.tcp://localhost:8184/fault");
}
#endregion
}
}
客户端code:
Client code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.ServiceModel.Dispatcher;
namespace TestWCFClient
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("CLIENT");
try
{
NetTcpBinding binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.Message; //If you remove this line the code works!!!!
Uri address = new Uri("net.tcp://localhost:8184/");
EndpointAddress endpoint = new EndpointAddress(address);
HelloWorldServiceClient client = new HelloWorldServiceClient(binding, endpoint);
Console.WriteLine("Calling client with a valid parameter...");
Console.WriteLine(client.SayHello("Davide"));
Console.WriteLine("OK");
Console.WriteLine("Calling client with an invalid parameter...");
Console.WriteLine(client.SayHello(null)); //This call causes the timeout when Security is set to Message
Console.WriteLine("OK");
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.WriteLine("Press enter to exit");
Console.ReadLine();
}
}
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
string SayHello(string name);
}
class HelloWorldServiceClient : System.ServiceModel.ClientBase, IHelloWorldService
{
public HelloWorldServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress address) :
base(binding, address)
{ }
public string SayHello(string name)
{
return base.Channel.SayHello(name);
}
}
}
如果我删除 binding.Security.Mode = SecurityMode.Message;
在客户端和服务器上的异常被正确翻译客户端可以看到它没有线的问题。
If I remove the binding.Security.Mode = SecurityMode.Message;
line on the client and on the server the exception is correctly translated and the client can see it without problems.
在WCF的日志我看到这些消息:
没有签名的消息部分中指定的与的net.tcp://本地主机:8184 /故障的消息。动作
该安全协议不能确保传出消息。
On the WCF log I see these messages:
No signature message parts were specified for messages with the 'net.tcp://localhost:8184/fault' action.
The security protocol cannot secure the outgoing message.
在如何解决这个问题的任何想法?看来我必须签署/加密的错误消息,但我不知道如何...
如果我用运输安全code按预期工作。
Any idea on how to solve this problem? Seems that I must sign/encrypt the error message but I don't known how...
If I use Transport security the code works as expected.
谢谢!
推荐答案
这可能会有点来不及反应,但我有同样的问题,我想通了:
It might be a bit late to respond but I had the same issue and I figured it out:
您需要定义 FaultContract
你的接口方法以及 OperationContract的
。看看这里。
You need to define FaultContract
on your interface methods along with OperationContract
. Have a look here.
Sooooooooooo痛苦的,但最终想通了,和现在的作品。
Sooooooooooo painful but finally figured out and works now.
这篇关于使用IErrorHandler和TCP信息安全造成超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!