I have a WCF service with a user connection IServiceBehavior used to return a specific client-side error. When I enable this code using TCP Message Security, I get a service timeout.
Below you can see the full client and server code to reproduce the error.
Server 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
}
}
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; , , .
WCF :
"net.tcp://localhost: 8184/fault" .
.
, ? , / , , ...
, , .
!