I have a WCF service with a CallbackContract. The service is exposed to a Silverlight client using "pollingDuplexHttpBinding"
When the Silverlight client is "dead" and the service calls a callback operation, it gets a timeout exception after one minute.
How can I set this timeout to be different?
Thanks,
Elad
There is a nice article in MSDN related to configuring PollingDuplexHttpBinding:
//Inactivity timeout
PollingDuplexHttpBinding binding = new PollingDuplexHttpBinding();
//Get default inactivity timeout
TimeSpan defaultInactivityTimeOut = binding.InactivityTimeout;
//Returns default timeout in minutes: 10
string txtDefaultInactivityTimeOut = defaultInactivityTimeOut.Minutes.ToString();
//Set new inactivity timeout
TimeSpan newInactivityTimeOut = new TimeSpan(0, 5, 0);
binding.InactivityTimeout = newInactivityTimeOut;
UPDATE: Under 'To use PollingDuplexHttpBinding' paragraph of 'How to: Build a Duplex Service for a Silverlight Client' there is web.config based example configuring PollingDuplexHttpBinding.
Hope, this will help.
So it seems that the "SendTimeout" attribute of PollingDuplexHttpBinding does the job:
<extensions>
<bindingExtensions>
<add name="pollingDuplexHttpBinding" type="System.ServiceModel.Configuration.PollingDuplexHttpBindingCollectionElement, System.ServiceModel.PollingDuplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</bindingExtensions>
</extensions>
<bindings>
<pollingDuplexHttpBinding>
<binding name="myPollingDuplex" sendTimeout="00:00:05"/>
</pollingDuplexHttpBinding>
</bindings>
<services>
<service name="Kodak.Pgy.Server.Event.WCFService.EventService" behaviorConfiguration="EventBehavior">
<!--For duplex communication with the service from silverlight client-->
<endpoint address="/for-silverlight" binding="pollingDuplexHttpBinding" bindingConfiguration="myPollingDuplex" contract="IEventService"/>
</service>
</services>
Related
We have a WCF service that listens to an Azure servicebus queue using the NetMessagingBinding. However we are finding that sometimes the service seems to stop being notified when messages arrive, ie we see the queue build up but none of our instances process the messages.
If we then reboot the instances they immediately start receiving messages from the queue again.
The code which opens the WCF service in our worker role:
var endpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(ICacheKeyExchangeWithSession)))
{
Address = new EndpointAddress(new Uri(baseAddress + QueueNames.Cache)),
Binding = new NetMessagingBinding(),
};
var endpointBehavior = new TransportClientEndpointBehavior
{
TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(id, secret),
};
endpoint.EndpointBehaviors.Add(endpointBehavior);
host = new ServiceHost(typeof(DataService), new Uri[] { });
host.AddServiceEndpoint(endpoint);
host.Open();
and we have no specific config in the app.config for the NetMessagingBinding:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<extensions>
<behaviorExtensions>
<add name="transportClientEndpointBehavior" type="Microsoft.ServiceBus.Configuration.TransportClientEndpointBehaviorElement, Microsoft.ServiceBus, Version=1.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</behaviorExtensions>
<bindingElementExtensions>
<add name="netMessagingTransport" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingTransportExtensionElement, Microsoft.ServiceBus, Version=1.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</bindingElementExtensions>
<bindingExtensions>
<add name="netMessagingBinding" type="Microsoft.ServiceBus.Messaging.Configuration.NetMessagingBindingCollectionElement, Microsoft.ServiceBus, Version=1.8.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</bindingExtensions>
</extensions>
</system.serviceModel>
Any ideas?
From what you've described, it sounds like you may be victim of your IIS configuration: you need to ensure iis isn't configured to automatically recycle your application pool that runs your app. If you don't also have application initialization configured in iis, your service won't restart automatically and resume processing messages
I have strange problem with WCF service. I use pollingDuplexBinding and Silverlight client.
Binding was registred by this code in web.config
<bindingElementExtensions>
<add name="pollingDuplex" type="System.ServiceModel.Configuration.PollingDuplexElement, System.ServiceModel.PollingDuplex" />
</bindingElementExtensions>
On first call everything is ok - service returns data fast. But second call executes more than 5 mitutes. If I set big timeouts, result will be returned to client, else it throws TimeoutException. WCF method I'm calling does nothing - just returns short string.
WCF tracing says, that second service call just coming 5 minutes later than client calls this method, and executes quickly.
I use these service attributes:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
It's client code
var binding = new PollingDuplexHttpBinding(PollingDuplexMode.SingleMessagePerPoll);
var address = new EndpointAddress("/SportService.svc");
_proxy = new SportDuplexClient(binding, address);
i hade same problem, i solve it in this way :
just set aspNetCompatibilityEnabled="false" to false in web.config file
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
or set sessionState mode="Off" in web.config
<system.web>
<sessionState mode="Off" />
</system.web>
in both way my problem will solved...
One of my WCF Services has an operation contract taking a large sized file as a parameter. So, when the client tries to send this over, I got an exception and when I looked at the server trace this is what I saw:
MESSAGE: The maximum message size quota for incoming messages (65536)
has been exceeded. To increase the quota, use the
MaxReceivedMessageSize property on the appropriate binding element.
I was using the default simplified configuration for my WCF services, so added a new service definition as follows:
<system.serviceModel>
<services>
<service name="MyNamespace.MyService">
<endpoint address="MyService.svc"
binding="basicHttpBinding" bindingConfiguration="basicHttp"
contract="MyNamespace.IMyService" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding name="basicHttp" allowCookies="true"
maxReceivedMessageSize="10485760"
maxBufferSize="10485760"
maxBufferPoolSize="10485760">
<readerQuotas maxDepth="32"
maxArrayLength="10485760"
maxStringContentLength="10485760"/>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
...
</behaviors>
<protocolMapping>
...
</protocolMapping>
The way I consume my services is, I have a function returning a channel in my helper class, and I use that channel to call the operations:
public static T CreateChannel<T>() where T : IBaseService
{
System.ServiceModel.BasicHttpBinding binding= new System.ServiceModel.BasicHttpBinding();
binding.TransferMode = TransferMode.Streamed;
binding.Security = new BasicHttpSecurity() { Mode = BasicHttpSecurityMode.None };
binding.MaxReceivedMessageSize = 10485760;
binding.MaxBufferSize = 10485760;
System.ServiceModel.ChannelFactory<T> cf2 = new ChannelFactory<T>(binding,
new System.ServiceModel.EndpointAddress(MyEndpointAddress)); //I checked this part, the address is correct.
T Channel= cf2.CreateChannel();
return Channel;
}
and then,
var businessObject = WcfHelper.CreateChannel<IMyService>();
var operationResult = await businessObject.MyOperationAsync(...);
Even though, my other services are running correctly, the one I defined in the configuration explicitly returns an exception of "There was no endpoint listening..." I am developing on VS2012, using IISExpress. What may be the problem, any suggestions?
I think there is a mismatch for transfert mode. In client-side, you are are using streamed transfert whereas in server-side it is not in the config. In addition, you have specified 10MB, which is not so high.
Please visit this for more info on streaming.
Edit :
If you are hosting under IIS, please also check (default is 4Mb) :
<system.web>
<httpRuntime maxRequestLength="4096 " />
</system.web>
I have a self hosted WCF 4 service, catering the same contract via basicHttpBinding for Silverlight 4 clients and wsHttpBinding for the others. The code is very short and simple and provided here.
I get the following error when trying to access the a service method from WCF:
Message=An error occurred while trying to make a request to URI
http://localhost:8008/WCF4Silverlight.MyService/SL. This could be
due to attempting to access a service in a cross-domain way without a
proper cross-domain policy in place, or a policy that is unsuitable
for SOAP services. You may need to contact the owner of the service to
publish a cross-domain policy file and to ensure it allows
SOAP-related HTTP headers to be sent. This error may also be caused by
using internal types in the web service proxy without using the
InternalsVisibleToAttribute attribute. Please see the inner exception
for more details.
I do have the method, GetClientAccessPolicy() serving the cross-domain policy using WebGet attribute, and I am kind of sure that there is a problem with it getting exposed properly. Your insight into the problem will be highly appreciated. If I type http://localhost:8008/WCF4Silverlight.MyService/clientaccesspolicy.xml in the browser, I do get the xml for the same, but the call from Silverlight always fails with the above error.
Here is the code for the WCF service:
namespace WCF4Silverlight
{
[ServiceContract(SessionMode = SessionMode.NotAllowed)]
public interface IClientAccessPolicy
{
[OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
Stream GetClientAccessPolicy();
}
}
namespace WCF4Silverlight
{
public class MyService: IMyService, IClientAccessPolicy
{
public Stream GetClientAccessPolicy()
{
const string result = #"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers=""*"">
<domain uri=""*""/>
</allow-from>
<grant-to>
<resource path=""/"" include-subpaths=""true""/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>";
if (WebOperationContext.Current != null)
WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml"; return new MemoryStream(Encoding.UTF8.GetBytes(result));
}
}
//Other service methods....
}
Here is code that publishes the service:
class Program
{
static void Main(string[] args)
{
ServiceHost myServiceHost = new ServiceHost(typeof(MyService));
myServiceHost.Open();
//Wait for client action.
myServiceHost.Close();
}
}
Here is the app.config for the WCF service host:
<service name="WCF4Silverlight.MyService" behaviorConfiguration="MyServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8008/MyService/"/>
</baseAddresses>
</host>
<endpoint address="general" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMyService" contract="WCF4Silverlight.IMyService"/>
<endpoint address="SL" binding="basicHttpBinding" bindingConfiguration="basicHttpBinding_IMyService" contract="WCF4Silverlight.IMyService"/>
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBinding_IMyService" behaviorConfiguration="webHttpBehavior" contract="WCF4Silverlight.IClientAccessPolicy" />
</service>
And here is the ServiceReferences.ClientConfig for the Silverlight client:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IMyService" maxBufferSize="2147483647"
maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</basicHttpBinding>
<customBinding>
<binding name="WSHttpBinding_IMyService">
<textMessageEncoding messageVersion="Default" writeEncoding="utf-8" />
<httpTransport maxReceivedMessageSize="2147483647" maxBufferSize="2147483647" />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:8008/MyService/SL"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IMyService"
contract="myWCFService.IMyService" name="BasicHttpBinding_IMyService" />
</client>
</system.serviceModel>
This is what I did to resolve the issue:
1) Used Fiddler to see where the WCF calls were directed. Fiddler told that the calls were failing to HOST - http:/localhost:8008 and URL - /clientaccesspolicy.xml.
2) Created a different class ClientAccessPolicy implementing IClientAccessPolicy (with WebGet for /clientaccesspolicy.xml).
3) Added another section in app.config of the host for a new service hosting the Clientaccesspolicy class. This one had its base address as http:/localhost:8008/
<service name="WCF4Silverlight.ClientAccessPolicy" behaviorConfiguration="ClientAccessPolicyBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8008/"/>
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webHttpBinding_IMyService" behaviorConfiguration="webHttpBehavior" contract="WCF4Silverlight.IClientAccessPolicy" />
</service>
4) In the hosting code, created another instance of ServiceHost and launched the new service with Clientaccesspolicy
ServiceHost clientAccessPolicyHost = new ServiceHost(typeof(ClientAccessPolicy)); clientAccessPolicyHost.Open();
5) In the Silverlight client, deleted the existing reference to the WCF and added the one to the newly hosted service.
The WCF calls from Silverlight are now going through.
Self hosted services on machines without IIS where the clientaccesspolicy can't be served up from the root, can instead use this method to dynamically serve up the policy on Port 80:
http://blogs.msdn.com/b/carlosfigueira/archive/2010/07/25/enabling-cross-domain-calls-for-sl-apps-on-self-hosted-tcp-services.aspx
The easiest way to debug this kind of issues is by using Fiddler (www.fiddler2.com) to intercept the HTTP traffic. You'll immediately see if clientAccessPolicy.xml is requested, where it is expected to be, and what is the result.
If you get a 404 (resource not found) the file is not at the expected location (but your webGet annotation looks good to me), otherwise the issue is within the xml itself.
This is a very permissive clientAccessPolicy.xml that I usually use for development/testing purposes:
<?xml version="1.0" ?>
<cross-domain-policy>
<allow-access-from domain="*" />
</cross-domain-policy>
If you're using a self-hosted web service, you need to throw your ClientAccessPolicy.xml into the root of a website that can be reached on port 80 of your machine (e.g., http://localhost:80/ClientAccessPolicy.xml). This was new in Silverlight 4, and unfortunately, I haven't found it clearly explained in the MS docs. (It's mentioned, but it's not terribly clear.)
How do I increase the default timeout to larger than 1 minute on a WCF service?
Are you referring to the server side or the client side?
For a client, you would want to adjust the sendTimeout attribute of a binding element. For a service, you would want to adjust the receiveTimeout attribute of a binding elemnent.
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="longTimeoutBinding"
receiveTimeout="00:10:00" sendTimeout="00:10:00">
<security mode="None"/>
</binding>
</netTcpBinding>
</bindings>
<services>
<service name="longTimeoutService"
behaviorConfiguration="longTimeoutBehavior">
<endpoint address="net.tcp://localhost/longtimeout/"
binding="netTcpBinding" bindingConfiguration="longTimeoutBinding" />
</service>
....
Of course, you have to map your desired endpoint to that particular binding.
Under the Tools menu in Visual Studio 2008 (or 2005 if you have the right WCF stuff installed) there is an options called 'WCF Service Configuration Editor'.
From there you can change the binding options for both the client and the services, one of these options will be for time-outs.
You can choose two ways:
1) By code in the client
public static void Main()
{
Uri baseAddress = new Uri("http://localhost/MyServer/MyService");
try
{
ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService));
WSHttpBinding binding = new WSHttpBinding();
binding.OpenTimeout = new TimeSpan(0, 10, 0);
binding.CloseTimeout = new TimeSpan(0, 10, 0);
binding.SendTimeout = new TimeSpan(0, 10, 0);
binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
serviceHost.AddServiceEndpoint("ICalculator", binding, baseAddress);
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
}
catch (CommunicationException ex)
{
// Handle exception ...
}
}
2)By WebConfig in a web server
<configuration>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding openTimeout="00:10:00"
closeTimeout="00:10:00"
sendTimeout="00:10:00"
receiveTimeout="00:10:00">
</binding>
</wsHttpBinding>
</bindings>
</system.serviceModel>
For more detail view the official documentations
Configuring Timeout Values on a Binding
Class WSHttpBinding
Different timeouts mean different things. When you're working on the client.. you're probably looking mostly at the SendTimeout - check this reference - wonderful and relevant explanation:
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/84551e45-19a2-4d0d-bcc0-516a4041943d/
It says:
Brief summary of binding timeout knobs...
Client side:
SendTimeout is used to initialize the OperationTimeout, which governs the whole interaction for sending a message (including receiving a reply message in a request-reply case). This timeout also applies when sending reply messages from a CallbackContract method.
OpenTimeout and CloseTimeout are used when opening and closing channels (when no explicit timeout value is passed).
ReceiveTimeout is not used.
Server side:
Send, Open, and Close Timeout same as on client (for Callbacks).
ReceiveTimeout is used by ServiceFramework layer to initialize the session-idle timeout.
In addition to the binding timeouts (which are in Timespans), You may also need this as well. This is in seconds.
<system.web>
<httpRuntime executionTimeout="600"/><!-- = 10 minutes -->