I have a piece of code that calls a WCF service that is hosted on a server.
The code keeps looping around and around calling this method over and over again. (It's asking for a 'status', so it's not doing any work at all).
That's fine except that after a short period of time I get an error:
This request operation sent to net.tcp://serverName:9001/service1 did not receive a reply within the configured timeout (00:00:09.9843754)
And suddenly i cannot get to the server at all EVER. I increased the timeout to 1min but still the same problem. Note that the program that hosts the service is doing nothing else, just offering it's 'status'. So it's not an issue with the WCF service app being busy.
I think it's a problem with the code calling the service because when i re-start the app it can connect to the service just fine ... until after another short time i get the timeout error again. For this reason i don't thnk it's a network error either, as when I restart the app it's ok for a period of time.
Here is the code i use to call the service. Do i need to dispose of the ChannelFactory after each call to clean it up or what am i doing worng?
NetTcpBinding binding = new NetTcpBinding(SecurityMode.Message);
binding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
EndpointAddress endPoint = new EndpointAddress(new Uri(clientPath));
ChannelFactory<IClient> channel = new ChannelFactory<IClient>(binding, endPoint);
channel.Faulted += new EventHandler(channel_Faulted);
IClient client = channel.CreateChannel();
((IContextChannel)client).OperationTimeout = new TimeSpan(0, 0, 10);
ClientStatus clientStatus = client.GetStatus();
You do have to close client connections after you finish calling GetStatus. The best way to do this is to use a using block. But you can also do something like this after your call client.GetStatus()
ClientStatus clientStatus = client.GetStatus();
try
{
if (client.State != System.ServiceModel.CommunicationState.Faulted)
{
client.Close();
}
}
catch (Exception ex)
{
client.Abort();
}
Related
I am working with a c# program within my network and am able to post messages to an Azure Service Bus queue. When receiving them, I get an exception on MessageReceiver.Receive(). The code and error is below;
MessagingFactory factory = MessagingFactory.CreateFromConnectionString(QueueConnectionString);
//Receiving a message
MessageReceiver testQueueReceiver = factory.CreateMessageReceiver(QueueName);
using (BrokeredMessage retrievedMessage = testQueueReceiver.Receive(new TimeSpan(0, 0, 20)))
{
try
{
var message = new StreamReader(retrievedMessage.GetBody<Stream>(), Encoding.UTF8).ReadToEnd();
retrievedMessage.Complete();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
retrievedMessage.Abandon();
}
}
The error gets thrown on the 'using' line at
testQueueReceiver.Receive(...);
The server rejected the upgrade request. 400 This endpoint is only for web-socket requests
I can't find anything on the web with the exception of one post which seems to suggest it is a firewall / ports issue. I have all the azure service bus ports outbound open (9350-9354, 80, 443) locally but there is a chance the 9000's are blocked at the firewall. Should it require these? Any pointers would be greatly appreciated !
Service MessagingCommunication Exception - The End point is only for web socket requests
I'm just wondering why don't you use OnMessage instead of polling the queue?
var connectionString = "";
var queueName = "samplequeue";
var client = QueueClient.CreateFromConnectionString(connectionString, queueName);
client.OnMessage(message =>
{
Console.WriteLine(String.Format("Message body: {0}", message.GetBody<String>()));
Console.WriteLine(String.Format("Message id: {0}", message.MessageId));
message.Complete()
});
This was fixed due to some proxy issues.
The account that the code was running under was an async service. I needed to log in as that account, open IE and go to connections (LAN) and remove the proxy checkboxes (detect settings automatically, etc). Once this was done, the code bypassed the proxy and worked fine.
The following code works just fine in WinForms:
if (System.Configuration.ConfigurationManager.AppSettings["Data.UseNamedPipes"] == "true")
{
AES.Cloud.DataAccessLayer.TheEDGEContext.UseLocalDb = true;
string address = "net.pipe://localhost/" + Guid.NewGuid() + "/DataManager";
var svc = AES.InProcFactory.CreateInstance<AES.Cloud.DataService.EstimatingDataService, AES.Cloud.DataService.IDataManager>(2147483647, 2147483647, address);
DataService<AES.TheEdge.Framework.Services.Contracts.IDataManager>._namedPipeAddress = address;
var ss = svc.GetNextKey(); //<-- Calling service here.
}
but when I use WPF it times out (exception at the bottom but it's useless) when I call the service, however if I invoke this code on a different thread it works just fine in WPF:
System.Threading.ThreadPool.QueueUserWorkItem( new System.Threading.WaitCallback( (o) =>{
//same code as above... no problem, no timeout, no blocking
}
Is there some issue using the startup/main thread to do this sort of thing? Confused in Jupiter...
Exception:
System.TimeoutException: This request operation sent to net.pipe://localhost/c1a59720-11fc-49c3-9d82-8185203a6f5d/DataManager did not receive a reply within the configured timeout (00:01:00). The time allotted to this operation may have been a portion of a longer timeout. This may be because the service is still processing the operation or because the service was unable to send a reply message. Please consider increasing the operation timeout (by casting the channel/proxy to IContextChannel and setting the OperationTimeout property) and ensure that the service is able to connect to the client.
I have an SOA application that uses a duplex WCF service hosted within a Windows Service. The client itself is a WPF application.
I'm seeing unusual behaviour on closing and restarting the client application. If I start a new instance after closing one, nothing visibly appears to happen. However, checking task manager shows the new instance is running as a background process. If I try to start another new instance of the client application, it will display the error screen I've written - stating an error with the service. Investigation has shown that the client cannot create a new instance of the service callback channel because another application has already registered the URL. This is a System.ServiceModel.AddressAlreadyInUseException.
If I then end the background client task in task manager, my client displaying the error message is then able to connect to the service and run as normal. I have also noticed that if I close the background task before starting a new instance, the new instance will also not appear.
My concern here is that this is not useable and feels like a real hassle for users. What could be going wrong? It seems as if something is not cleaning up unmanaged resource but I've used ANTS and can't identify it. The client is created as:
IServiceCallback callback = new Callback();
_context = new InstanceContext(callback);
_channelFactory = new DuplexChannelFactory<IMyService>(_context, binding, endpoint);
_proxy =
_channelFactory.CreateChannel();
((ICommunicationObject)_proxy).Open(TimeSpan.FromSeconds(5));
The Service's constructor uses the following code:
_callback = OperationContext.Current.GetCallbackChannel<IServiceCallback>();
var commObject = _callback as ICommunicationObject;
if (commObject != null)
{
commObject.Faulted += ChannelFaulted;
commObject.Closing += ChannelClosing;
commObject.Closed += ChannelClosed;
}
OperationContext.Current.Channel.Faulted += ChannelFaulted;
OperationContext.Current.Channel.Closed += ChannelFaulted;
Before closing, the client calls the service's Disconnect method, which does:
var commObject = _callback as ICommunicationObject;
if (commObject != null)
{
commObject.Faulted -= ChannelFaulted;
commObject.Closing -= ChannelClosing;
commObject.Closed -= ChannelClosed;
}
OperationContext.Current.Channel.Faulted -= ChannelFaulted;
OperationContext.Current.Channel.Closed -= ChannelFaulted;
Finally, the client closes the channels like this:
foreach (var incomingChannel in _context.IncomingChannels.ToArray())
{
incomingChannel.Close();
}
try
{
var proxy = _proxy as IChannel;
if (proxy != null)
{
proxy.Close();
}
}
catch (Exception)
{
_channelFactory.Abort();
}
Why am I seeing this unusual behaviour? Is there something I'm missing to close the channel or something I'm doing wrong to create it? Or is it likely that there must be an issue elsewhere in my code that keeps the channel or session alive?
**UPDATE: ** I have been trying a few things and found out that if I start a client instance, close it, then leave it for an hour, I can start another instance with no issue. I've also discovered that if I restart the Windows Service after creating and closing an instance of the client application then I'm also able to create another in those circumstances.
**UPDATE 2: ** Stepping through, I can see that the incomingChannel.Close() does not complete and does not throw an error. I've removed that section and also find proxy.Close() does not complete and does not throw an exception. I've tried using the overloads and added a timeout, but no timeout exception is being thrown. The Service's Dispose() method is not hit at all.
Try closing your channel factory too.
proxy.ChannelFactory.Close();
proxy.Close();
I have a very simple WCF service running.
An ASP.NET web application is consuming this service from code behind during pageload like this:
try
{
using (var myWCFClient = new MyWCFClient())
{
int myInt = myWCFClient.GetValue();
}
}
catch (Exception ex)
{
}
Where "MyWCFClient" is the proxy object which is autogenerated when adding a service reference to my project.
Everything works fine, but the problem is when the Service Endpoint is down for some reason, it takes more than 30 seconds for the EndpointNotFoundException is catched. Of course this is unacceptable because it delays pageload since everything is synchronous. And because i have no simple mechanism to push the data to the page async after pageload, an async call to the WCF service is not preferred.
I also tried to set the sentTimeout in web.config to 5 seconds, but this doen't solve the problem.
When is set the OperationTimeout of the InnerChannel to 5 seconds like this...
((IContextChannel)myWCFClient.InnerChannel).OperationTimeout = TimeSpan.FromSeconds(5);
...i do get a TimeOutException, but this exception is not throwed within 5 seconds, it also takes more than 30 seconds...
Does anybody knows how to handle this situation, or is there a way to quick check if the service is running before doing the actual call???
We use a ping function on the host that simply returns True in the response payload, and if you response takes longer than 5 seconds, we throw our own exception and exit the process. All the logic is on the client side, minus the Ping() function. We don't wait for the timeout exception.
I am trying to host a WCF service, using NetTcpBinding in a Windows service. (I'm going to use it as an API for various clients both Web and Windows32) Obviously, I am doing this within a test host before putting it in a Windows service.
I have the following contract:
namespace yyy.xxx.Server.API.WCF
{
[ServiceContract]
public interface ISecureSessionBroker
{
[OperationContract]
string GetSessionToken(string username, string encryptedPassword, string clientApiKey, string clientAddress);
}
}
with the following implementation:
namespace yyy.xxx.Server.API.WCF
{
public class SecureSessionBroker : ISecureSessionBroker
{
#region ~ from ISecureSessionBroker ~
public string GetSessionToken(string username, string encryptedPassword, string clientApiKey, string clientAddress)
{
return Guid.NewGuid().ToString();
}
#endregion
}
}
I am hosting the WCF service using the code below (within a class/method):
try
{
_secureSessionBrokerHost = new ServiceHost(typeof(SecureSessionBroker));
NetTcpBinding netTcpBinding = new NetTcpBinding();
_secureSessionBrokerHost.AddServiceEndpoint(typeof(ISecureSessionBroker), netTcpBinding, "net.tcp://localhost:8080/secureSessionBrokerTcp");
int newLimit = _secureSessionBrokerHost.IncrementManualFlowControlLimit(100);
// Open the ServiceHost to start listening for messages.
_secureSessionBrokerHost.Open();
}
catch (Exception ex)
{
throw;
}
The key thing here is that I do not want to have to rely on an App.config file. Everything must be configured programmatically. When I run this code, the service appears to come "up" and listen. (ie. I have no exceptions)
BUT when I use the client code below:
string secureSessionBrokerUrl = string.Format("{0}/secureSessionBrokerTcp","net.tcp://localhost/8080",url);
EndpointAddress endpointAddress=new EndpointAddress(secureSessionBrokerUrl);
System.ServiceModel.Channels.Binding binding = new NetTcpBinding();
yyy.xxx.Windows.AdminTool.API.WCF.SecureSessions.SecureSessionBrokerClient
client = new yyy.xxx.Windows.AdminTool.API.WCF.SecureSessions.SecureSessionBrokerClient(binding,endpointAddress);
string sessionToken=client.GetSessionToken("", "", ""); // exception here
MessageBox.Show(sessionToken);
... I always get an exception. At the moment, I am getting:
This request operation sent to
net.tcp://localhost:8080/secureSessionBrokerTcp
did not receive a reply within the
configured timeout (00:01:00). The
time allotted to this operation may
have been a portion of a longer
timeout. This may be because the
service is still processing the
operation or because the service was
unable to send a reply message.
Please consider increasing the
operation timeout (by casting the
channel/proxy to IContextChannel and
setting the OperationTimeout property)
and ensure that the service is able to
connect to the client.
So I guess it cannot resolve the service.
Where am I going wrong? How do I test for the existence of the service over TCP? I have used the SvcTraceViewer and I just get the same message, so no news there.
I would prefer to ask the user for a URL of the service, so they would enter "net.tcp://localhost:8080" or something, which would then be used as a BaseAddress for the various calls to the SecureSessionBroker (and other) WCF services ... without resorting to App.config.
Unfortunately, all the examples I can find all use the App.config.
Interestingly, I can host the service using the VS Host and the client connects fine. (Using:
D:\dev2008\xxx\yyy.xxx.Server>WcfSvcHost.exe /service:bin/debug/yyy.
xxx.Server.dll /config:App.config)
Ok, it came to me in a flash of inspiration.
I was using a Windows Form (alarm bells) to "host" the service. Clicking out of the form, I used a bit of code to call the service (included) on a button click. Of course, the service was not in its own thread, so the service could not respond.
I've fixed it by putting the Service container (which contains the host) within its own thread:
Thread thread = new Thread(new ThreadStart(_serviceWrapper.Start));
thread.Start();
The Start() method sets up the ServiceHost.
I incorrectly thought that while a WCF Service Host will create threads for incoming requests, it will only do this if it is in its own non-blocking thread (ie. not a UI thread).
Hope it helps someone else.