I am trying to understand "receiveTimeout" binding property in WCF by following code:
Server side:
ServiceHost serviceHostForStrong = new ServiceHost(typeof(Service), new Uri("http://localhost:8887/Service"));
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
basicHttpBinding.ReceiveTimeout = new TimeSpan(0, 0, 5);
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:8887/Service/");
ServiceEndpoint serviceEndpoint =
new ServiceEndpoint(ContractDescription.GetContract(typeof(IServiceContract)),
basicHttpBinding,
endpointAddress);
serviceHostForStrong.AddServiceEndpoint(serviceEndpoint);
serviceHostForStrong.Open();
Console.WriteLine("Service is running....Press any key to exit");
Console.ReadKey();
Client side:
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:8887/Service/");
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
ChannelFactory<IServiceContract> channelFactory = new ChannelFactory<IServiceContract>(basicHttpBinding, endpointAddress);
IServiceContract proxy = channelFactory.CreateChannel(endpointAddress);
Console.WriteLine("Data received: " + proxy.GetData());
Thread.Sleep(new TimeSpan(0, 0, 10));
Console.WriteLine("Data received after 10 seconds: " + proxy.GetData());
Console.WriteLine("Press any key to exit.....");
Console.ReadKey();
Please note:
The receiveTimeout property set on server side is 5 seconds.
I'm waiting for 20 seconds in GetData() method on server side before returning the data.
I'm waiting for 10 seconds on client side before sending another request.
The application works fine without any exception. Ideally, in my opinion, it should throw an exception (as per my understanding from the definition of MSDN for receiveTimeout).
Thoughts anyone?
Thanks!
ReceiveTimeout – used by the Service Framework Layer to initialize the session-idle timeout which controls how long a session can be idle before timing out.
So, to get that behavior you have to use wsHttpBinding binding (it supports session) instead of basicHttpBinding (no session, hence receive no timeout).
Related
I've got a method of connecting and use a WCF method, which is on HTTPS and requires a username and password in .net 4.
Now I need to do the same but within .Net 2 and I can't seem to get it to work. I keep on getting the below error. Can anyone help?
Error
{"The underlying connection was closed: An unexpected error occurred on a receive."}
Inner Exception
{"Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host."}
.Net 4 Original Code:
WSHttpBinding myBinding = new WSHttpBinding();
myBinding.Security.Mode = SecurityMode.Transport;
myBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;
EndpointAddress ea = new EndpointAddress(wcfURL);
var web = new Gateway.GatewayClient(myBinding, ea);
// var web = new Gateway.GatewayClient();
XMLCrypto crypto = new XMLCrypto();
web.ClientCredentials.UserName.UserName = crypto.DecryptString(username);
web.ClientCredentials.UserName.Password = crypto.DecryptString(password);
web.Open();
web.Inbound("HOLog", message.Trim().Replace("\n", "").Replace(#"\\", ""));
web.Close();
.Net 2 Code
XMLCrypto crypto = new XMLCrypto();
url = "http://..../gateway/gateway.svc";
userName = crypto.DecryptString(userName);
password = crypto.DecryptString(password);
var web = new Gateway.Gateway();
var credentials = new NetworkCredential(userName, password);
CredentialCache credentialCache = new CredentialCache();
credentialCache.Add(new Uri(url), "Basic", credentials);
web.Credentials = credentials;
string returnMessage = web.Inbound("LSOA", " ");
After a long trolling over the web and testing different ways of talking to a WCF method, I have found the reason why it does not work.
Currently the WCF is set to use wsHttpBinding and now I know that .net 2, does not support it. My work around was to change the Binding from wsHttpBinding to basicHttpBinding within the Web.config of the WCF.
To do this and not effect anything using the WCF, I have to create a seprate Sub domain that will ref a WCF with the config that has the corrected Binding.
"The wsHttpBinding is not compatible with the ASMX-style web references used in .NET 2.0."
How to consume WCF wsHttpBinding Service in application built in 2.0?
I have a WCF service self-hosted in my console application and trying to understand the hostNameComparisonMode binding attribute for basicHttpBinding. Here is my hosted WCF:
// Test for StrongWildCard
ServiceHost serviceHostForStrong = new ServiceHost(typeof(Service), new Uri("http://test1:8887/Service"));
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
basicHttpBinding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
EndpointAddress endpointAddress = new EndpointAddress("http://abc1:8887/Service/ForStrong");
ServiceEndpoint serviceEndpoint =
new ServiceEndpoint(ContractDescription.GetContract(typeof(IServiceContract)),
basicHttpBinding,
endpointAddress);
serviceHostForStrong.AddServiceEndpoint(serviceEndpoint);
serviceHostForStrong.Open();
// Test for Exact
ServiceHost serviceHostForExact = new ServiceHost(typeof(Service), new Uri("http://test2:8888/Service"));
basicHttpBinding = new BasicHttpBinding();
basicHttpBinding.HostNameComparisonMode = HostNameComparisonMode.Exact;
endpointAddress = new EndpointAddress("http://abc2:8888/Service/ForExact");
serviceEndpoint =
new ServiceEndpoint(ContractDescription.GetContract(typeof(IServiceContract)),
basicHttpBinding,
endpointAddress);
serviceHostForExact.AddServiceEndpoint(serviceEndpoint);
serviceHostForExact.Open();
// Test for Weak
ServiceHost serviceHostForWeak = new ServiceHost(typeof(Service), new Uri("http://test3:8889/Service"));
basicHttpBinding = new BasicHttpBinding();
basicHttpBinding.HostNameComparisonMode = HostNameComparisonMode.WeakWildcard;
endpointAddress = new EndpointAddress("http://abc3:8889/Service/ForWeak");
serviceEndpoint =
new ServiceEndpoint(ContractDescription.GetContract(typeof(IServiceContract)),
basicHttpBinding,
endpointAddress);
serviceHostForWeak.AddServiceEndpoint(serviceEndpoint);
serviceHostForWeak.Open();
Console.WriteLine("Service is running....Press any key to exit");
And here is my client side code:
EndpointAddress endpointAddress = new EndpointAddress("http://localhost:8887/Service/ForStrong/ABC"); // Why it doesn't match with StrongWildCard
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
ChannelFactory<IServiceContract> channelFactory = new ChannelFactory<IServiceContract>(basicHttpBinding, endpointAddress);
IServiceContract proxy = channelFactory.CreateChannel(endpointAddress);
Console.WriteLine("Data received: " + proxy.GetData());
Console.ReadKey();
As far as I understand from http://kennyw.com/?p=109, the URL "http://localhost:8887/Service/ForStrong/ABC" should match the StrongWildCard. However, it gives an exception at client when I try to run this code:
An unhandled exception of type 'System.ServiceModel.EndpointNotFoundException' occurred in mscorlib.dll Additional information: The message with To 'http://localhost:8887/Service/ForStrong/ABC' cannot be processed at the receiver, due to an AddressFilter mismatch at the EndpointDispatcher. Check that the sender and receiver's EndpointAddresses agree.
Am I missing anything here or my understand is incorrect? Few more supporting questions:
Can you give me few examples (considering this as base) where it
will use WeakWildCard URL?
How would I know which server side URL
served my request?
Thanks!
I'm fairly recent to WCF and trying to figure out the best way to accomplish my requirements.
I have an application hosting a WCF service with the following code:
Uri u1 = new
Uri("http://localhost:8732/Client1/WcfServiceLibrary1/Service1/"); Uri
u2 = new
Uri("http://localhost:8732/Client1/WcfServiceLibrary1/Service1/mex");
WSHttpBinding binding = new WSHttpBinding();
sHost = new ServiceHost(typeof(WcfServiceLibrary1.Service1), u1);
ServiceMetadataBehavior meta = new ServiceMetadataBehavior();
meta.HttpGetEnabled = true;
sHost.AddServiceEndpoint(typeof(WcfServiceLibrary1.IService1), binding, u1);
sHost.Description.Behaviors.Add(meta); sHost.Open();
I can create a service reference on a client application and call methods on this service no problems. using the code below.
remoteService.Service1Client client = new remoteService.Service1Client();
remote.Text = client.GetData(3);
I can also call a method without a service reference.
EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8732/Client1/WcfServiceLibrary1/Service1/");
WSHttpBinding myBinding = new WSHttpBinding();
ChannelFactory<IService1> ServiceConnectionFactory = new ChannelFactory<IService1>(myBinding, myEndpoint);
IService1 serviceConnection = ServiceConnectionFactory.CreateChannel();
If I try to execute the same code in the host application it get the error below.
The request channel timed out while waiting for a reply after
00:01:00. Increase the timeout value passed to the call to Request or
increase the SendTimeout value on the Binding. The time allotted to
this operation may have been a portion of a longer timeout.
How can a application consume and use a WCF service that it is currently hosting? Do I need to open the service in a thread of its own?
The idea is for the host to trigger some initialization before clients connect.
I'm using Castle WCF Integration Facility and I have everything working properly for my first webHttp endpoint. For this endpoint to work, it requires that the endpoint have the WebHttpBehavior enabled. I was able to achieve this using:
container.Register(Component.For<IEndpointBehavior>()
.ImplementedBy<WebHttpBehavior>());
This becomes a problem when I try to enable a second endpoint using BasicHttpBinding which is not compatible with the WebHttpBehavior.
Is there someway to specify that the IEndPointBehavior registration above is only applicable to a certain endpoint?
This is my full installer for the service:
container.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero)
.Register(Component.For<IDiagnosticService>()
.ImplementedBy<DiagnosticService>()
.Named("DiagnosticService")
.LifestyleTransient()
.AsWcfService(new DefaultServiceModel()
.Hosted()
.AddEndpoints(WcfEndpoint.BoundTo(new WebHttpBinding()).At("json"))
.AddEndpoints(WcfEndpoint.BoundTo(new BasicHttpBinding()).At("soap"))
.PublishMetadata(o => o.EnableHttpGet())));
container.Register(Component.For<IEndpointBehavior>()
.ImplementedBy<WebHttpBehavior>());
Ok. I finally figured this out. Turns out that the majority of my problem had to do with the Azure emulation environment rather than Castle WCF Integration. The answer is pretty straight forward -- just setup the ServiceEndpoint instances and use the WcfEndpoint.FromEndpoint() method.
Here is my working installer:
String internalEndpointAddress = string.Format("http://{0}/DiagnosticService.svc",
RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["Endpoint1"].IPEndpoint);
// This ContractDescription instance must be used for both endpoints in this case
ContractDescription description = ContractDescription.GetContract(typeof(IDiagnosticService));
// Create JSON webHTTP Binding
WebHttpBinding webhttpbinding = new WebHttpBinding();
string jsonURI = internalEndpointAddress + "/json";
EndpointAddress jsonEndpointAddress = new EndpointAddress(new Uri(jsonURI));
ServiceEndpoint jsonEndpoint = new ServiceEndpoint(description, webhttpbinding, jsonEndpointAddress);
jsonEndpoint.Behaviors.Add(new WebHttpBehavior());
// Create WSHTTP Binding
WSHttpBinding wsHttpBinding = new WSHttpBinding();
string soapURI = internalEndpointAddress + "/soap";
EndpointAddress soapEndpointAddress = new EndpointAddress(new Uri(soapURI));
ServiceEndpoint soapEndpoint = new ServiceEndpoint(description, wsHttpBinding, soapEndpointAddress);
container.AddFacility<WcfFacility>(f => f.CloseTimeout = TimeSpan.Zero)
.Register(Component.For<IDiagnosticService>()
.ImplementedBy<DiagnosticService>()
.Named("DiagnosticService")
.LifestyleTransient()
.AsWcfService(new DefaultServiceModel()
.Hosted()
.AddEndpoints(WcfEndpoint.FromEndpoint(jsonEndpoint))
.AddEndpoints(WcfEndpoint.FromEndpoint(soapEndpoint))
.PublishMetadata(o => o.EnableHttpGet())));
I have a wcf service I am setting up to run under IIS 7. I have the service set to streaming for the transfermode.
When I self host the service in a console application every thing seems to work ok. But when the client connects to an iis hosted service it seems to be buffering, and the client eventual times out. I have used fiddler to determine that this client time out happens before the http request is even made.
Here is the servers binding.
var binding = new CustomBinding();
binding.Elements.Add( new TextMessageEncodingBindingElement()
{
MessageVersion = MessageVersion.Soap12WSAddressing10
} );
var secBinding = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
secBinding.AllowInsecureTransport = true;
binding.Elements.Add( secBinding );
binding.Elements.Add( new HttpTransportBindingElement()
{
TransferMode = TransferMode.Streamed,
MaxReceivedMessageSize = Int32.MaxValue,
} );
And the client binding:
var binding = new CustomBinding();
binding.Elements.Add( new TextMessageEncodingBindingElement()
{
MessageVersion = MessageVersion.Soap12WSAddressing10
} );
var secBinding = SecurityBindingElement.CreateUserNameOverTransportBindingElement();
secBinding.AllowInsecureTransport = true;
binding.Elements.Add( secBinding );
binding.Elements.Add( new HttpTransportBindingElement()
{
TransferMode = TransferMode.Streamed,
MaxReceivedMessageSize = Int32.MaxValue,
MaxBufferSize = 400
} );
As an aside the connection is timing out because the stream is infinite and the server should read the first few bytes and then close the stream.
Recently, we had the same issue. When you host your service under IIS, no matter if you enable streaming or not, your service will buffer the entire message prior to sending it. The reason for this, is that it appears as though WCF does not set the Response.BufferOutput to "false" (default is true), when streaming is enabled on a service. A workaround can be found here:
http://weblogs.asp.net/jclarknet/archive/2008/02/14/wcf-streaming-issue-under-iis.aspx
Are you closing the Stream in the client? If true, try closing just in the service side.
Also, verify if its a OneWay operation.
Can you post the both binding nodes, for the endpoints?