I'm having a little problem with a WCF client. First, allow me to explain and give you details.
I'm currently developing a system, and I was thinking in separate the main application because I designed it to be updated with dlls. So I found MEF, and began to read a lot about it. But there was problem with MEF, it locks the file, no write. Then I found shadow copy. So now I placed the client in another AppDomain in the main Application. I've read that communication cross domains is possible through NET Remoting, so I made research and done it with WCF.
The main Application is the host, it loads the assembly in a new domain and starts the client. As the client is a DLL, there is no AppConfig file to load bindings, endpoints. I've created a class that helps me with that, so the config is added programatically.
Finally, it works!
But there is a little thing I don't think is ok. In the client, when the instruction DuplexClientBase.Open() is executed, it takes 20 seconds to open. I think is not OK 'cause when I move the client to a EXE (remember is a DLL and the config is added programatically) it doesn't take all that time.
Maybe is something wrong in the config, but I can't find it. So here are the souce code files. First, this is the App.config file, when the client is in a console application:
<configuration>
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="TcpBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" transactionFlow="false"
transferMode="Buffered" transactionProtocol="OleTransactions"
hostNameComparisonMode="StrongWildcard" listenBacklog="10"
maxBufferPoolSize="524288" maxBufferSize="65536" maxConnections="10"
maxReceivedMessageSize="65536">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00"
enabled="false" />
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign" />
<message clientCredentialType="Windows" />
</security>
</binding>
</netTcpBinding>
<wsDualHttpBinding>
<binding name="HttpBinding" closeTimeout="00:01:00" openTimeout="00:01:00"
receiveTimeout="00:10:00" sendTimeout="00:01:00" bypassProxyOnLocal="false"
transactionFlow="false" hostNameComparisonMode="StrongWildcard"
maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
<reliableSession ordered="true" inactivityTimeout="00:10:00" />
<security mode="Message">
<message clientCredentialType="Windows" negotiateServiceCredential="true"
algorithmSuite="Default" />
</security>
</binding>
</wsDualHttpBinding>
</bindings>
<client>
<endpoint address="net.tcp://localhost:8080/ProtoServicio/EPServicioTcp"
binding="netTcpBinding" bindingConfiguration="TcpBinding"
contract="TestServicio.IServicio" name="TcpBinding">
<identity>
<userPrincipalName value="OlinzerLaptopV\Olinzer" />
</identity>
</endpoint>
<endpoint address="http://localhost:8081/ProtoServicio/EPServicioHttp"
binding="wsDualHttpBinding" bindingConfiguration="HttpBinding"
contract="TestServicio.IServicio" name="HttpBinding">
<identity>
<userPrincipalName value="OlinzerLaptopV\Olinzer" />
</identity>
</endpoint>
</client>
</system.serviceModel>
And now, this is the code that creates the binding and endpoint:
internal static Binding GetBinding()
{
WSDualHttpBinding binding = new WSDualHttpBinding();
TimeSpan span = new TimeSpan( 0, 1, 0 );
binding.Name = "HttpBinding";
binding.CloseTimeout = span;
binding.OpenTimeout = span;
binding.ReceiveTimeout = span;
binding.SendTimeout = span;
binding.BypassProxyOnLocal = false;
binding.TransactionFlow = false;
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.MaxBufferPoolSize = 524288;
binding.MaxReceivedMessageSize = 65536;
binding.MessageEncoding = WSMessageEncoding.Text;
binding.TextEncoding = Encoding.UTF8;
binding.UseDefaultWebProxy = true;
binding.ReaderQuotas = new XmlDictionaryReaderQuotas();
binding.ReaderQuotas.MaxDepth = 32;
binding.ReaderQuotas.MaxStringContentLength = 8192;
binding.ReaderQuotas.MaxArrayLength = 16384;
binding.ReaderQuotas.MaxBytesPerRead = 4096;
binding.ReaderQuotas.MaxNameTableCharCount = 16384;
binding.ReliableSession = new ReliableSession();
binding.ReliableSession.Ordered = true;
binding.ReliableSession.InactivityTimeout = span;
binding.Security.Mode = WSDualHttpSecurityMode.Message;
binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
binding.Security.Message.NegotiateServiceCredential = true;
binding.Security.Message.AlgorithmSuite = SecurityAlgorithmSuite.Default;
return binding;
}
The file created by the code only contains the Http Endpoint. Maybe adding the tcp endpoint could make the diference, but, I have no idea how to make it. The function above is called by the constructor of the ClientClientBase class.
ServiceModel.DuplexClientBase<Servicio> MyClient = new ...<Servicio>(new InstanceContext(this), GetBinding(), GetEndpoint());
Feel free to notify me if you need anything else.
You are doing cross AppDomain communication within single process and you are using WsHttpBinding
? Do you understand how big overhead this has? It also highly increases complexity of your application deployment. It is probably not source of your main problem but I would start with:
WsDualHttpBinding
with NetNamedPipeBinding
To diagnosing your issue start with WCF tracing and check which operation on both client and server takes a long time - there can be problem with some security resolving because your setting uses message security.