WCF web service stops responding after several repeated calls - wcf

I have Windows applications that communicate to the logic layer and data layer with a WCF web service.
When the form is opened the connection to the web service is established and the connection is kept alive as long as the form is opened. On closing the from, the connection is closed using Finalize and Dispose on the web service.
After several times opening and closing forms, the service stops responding and I need to reset service which hosted in the IIS to get it working again. Any hints on how to proceed with this issue?
this is my service contract:
[ServiceContract]
public interface ICommandInvoker : IDisposable
{
[OperationContract(IsOneWay = false)]
void Initialize(TypeInfo managerType, UserInfo userInfo, Dictionary<string,string> settingDic);
[OperationContract(IsOneWay = true)]
void Finalize();
[OperationContract(IsOneWay = false, Action="*")]
//[CustomOperationBehavior]
ServerResult Execute(ServerCommand command);
[OperationContract(IsOneWay = false, Name="Execute Serialized")]
string Execute(string command, TypeInfo typeInfo);
[OperationContract(IsOneWay = false, Name = "Execute 2 Non Serialized")]
ServerResult Execute(TypeInfo mangerType, UserInfo userInfo, ServerCommand command);
[OperationContract(IsOneWay = false, Name = "Execute 2 Serialized")]
string Execute(TypeInfo mangerType, UserInfo userInfo, string command, TypeInfo typeInfo);
[OperationContract(IsOneWay = true)]
void BeginExecute(ServerCommand command);
and this is my Service
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class BudgetService : BaseCommandInvoker<BudgetDataContext>, IBudgetService
{
public BudgetService()
{
}
}
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IBudgetService : ICommandInvoker
{
}
Do you have any sample program for this method of use Wcf?
thank you

Could be lots of things!
Is the server returning a timeout? How are you managing your try catch blocks? Are any errors being thrown. I would check if the channel has faulted because an Exception will fault the channel. Your service should be throwing FaultExceptions if something goes wrong.
Impossible to really help ant more without more information.

Related

WCF Winform freezes when opened by server

I've written a VSTO Outlook Add-In and am trying to open a form in a separate Winform app when the user pushes a button on the Add-In, passing an integer as argument. I'm using WCF Named Pipe Binding. The Add-In is the client and the Winform app is the server. The binding and inter-process communication works fine. However, when the target form opens, it freezes with a spinning cursor. The form otherwise works fine from within the Winform app.
Per the code below, when I call "clsActivity.EditT("", activityID);" within the server method, it opens a form which is properly created and displayed, but then locks up with a spinning cursor and is inaccessible. I've been assuming that there is some element of the servicehost or other WCF process that is uncompleted, but can't identify the issue.
I've spent several days trying to find an answer. As I'm pretty new to WCF, I'm not even sure if I'm asking the right questions. Any assistance would be greatly appreciated. Thanks.
Server
// Service Contract
[ServiceContract(Namespace = "ComsIPC")]
interface ComsIPCContract
{
[OperationContract(IsOneWay = true)]
void OpenActivity(int activityID);
}
// Server Implementation
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class ComsIPCServer : ComsIPCContract
{
public void OpenActivity(int activityID)
{
try
{
clsActivity.EditT("", activityID);
}
catch
{
MessageBox.Show("Error in ComsIPCServer");
}
}
public void CreateComsIPCServerHost()
{
string address = "net.pipe://localhost/coms/IPC";
ServiceHost serviceHost = new ServiceHost(typeof(ComsIPCServer));
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
serviceHost.AddServiceEndpoint(typeof(ComsIPCContract), binding, address);
serviceHost.Open();
}
}
Client
// Service Contract
[ServiceContract(Namespace = "ComsIPC")]
interface ComsIPCContract
{
[OperationContract(IsOneWay = true)]
void OpenActivity(int activityID);
}
public class ComsIPCClient
{
public void OpenActivityInComs(int activityID)
{
string address = "net.pipe://localhost/coms/IPC";
NetNamedPipeBinding binding = new NetNamedPipeBinding(NetNamedPipeSecurityMode.None);
EndpointAddress ep = new EndpointAddress(address);
ComsIPCContract channel = ChannelFactory<ComsIPCContract>.CreateChannel(binding, ep);
channel.OpenActivity(activityID);
}
}

Closing WCF Connections from service

I have recently started a new job where WCF services are being used. I have used them in the past and am comfortable with them but from what I can recall if the client does not close the connection it has the ability to bring your service down entirely. I am aware of the proper procedure for closing the connections but if the responsibility is on the client, they may not follow the same practices and potentially have the ability to bring the service down. Is there any other way of handling the closing of the connections so that it is not reliant on the client doing the right thing? It seems odd that anyone who has access to your service has the ability to bring it down with such ease...
Thank you very much for any insights!
One option is to use session time out in the server. This actually faults the client channel.
There are only really three ways in which a session can terminated:
1) The client closes the proxy
2) The service's receiveTimeout is exceeded before the client sends another request
3) The service throws a non-fault exception which will fault the channel and so terminate the session
If you don't want the client involved then you only have 2 and 3 neither of which end well for the client - they will get an exception in both situation on the next attempt to talk to the service.
You could use Duplex messaging and get the service to notify the client that its requires session termination - the client then gets an opportunity to close down the proxy gracefully but this is a cooperative strategy
Or you need to use duplex (but still the client will have to call the service).
Here is some important points of the service implementation:
a: Use a static dictionary to keep the Client’s IP and callback channel. Before writing on the share object, lock the object.
b: Gets the IP address of the client using the GetAddressAsString method. You can get the IP of the client from the incoming message. The following statement shows how can we get the IP adddress of the Client in WCF:
RemoteEndpointMessageProperty clientEndpoint = OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
String ipAddress = clientEndpoint.Address;
If you are using the namepipe binding, you will not get the RemoteEndpointMessageProperty.
c: When the client creates the proxy of the service, it will call StartingService method immediately. Inside the StartingService method, I am keeping the callback channel of the client and current instance into the dictionary.
d: When the user of WCF service wants to disconnect a client, he/she will call the Disconnect method with the IP Address of the client.
e: The Disconnect method uses the IP Address to get the callback channel of the client and associate service instance of the client from the dictionary. Eventually, it notifies the client by using callback channel and close the incoming channel.
Here is the implementation through code:
[ServiceContract(CallbackContract=typeof(INotifyClientCallback),SessionMode=SessionMode.Required)]
public interface IService1
{
[OperationContract]
bool StartingService();
}
public interface INotifyClientCallback
{
[OperationContract(IsOneWay = true)]
void Disconnecting();
}
INotifyClientCallback interface for Callback.
Step 2: Implementation of the Contact:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class Service1 : IService1
{
private static readonly Dictionary subscribers = new Dictionary();
public static event EventHandler onClientAdded;
///
/// Returns the IP Address of the Client
///
///
public string GetAddressAsString()
{
if (!OperationContext.Current.IncomingMessageProperties.ContainsKey(RemoteEndpointMessageProperty.Name))
{
return "127.0.0.1";
}
RemoteEndpointMessageProperty clientEndpoint =
OperationContext.Current.IncomingMessageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
return clientEndpoint.Address;
}
public bool StartingService()
{
//Get the callback reference
INotifyClientCallback callback = OperationContext.Current.GetCallbackChannel();
string IPAddress = GetAddressAsString();
lock (subscribers)
{
if (!subscribers.ContainsKey(IPAddress))
{
subscribers[IPAddress] = new CommunicationStore()
{ NotifyCallback = callback,
IService = OperationContext.Current.InstanceContext
};
if (onClientAdded != null)
{
onClientAdded(IPAddress, null);
}
}
}
return true;
}
public static void Disconnect(string ipAddress)
{
if (subscribers.ContainsKey(ipAddress))
{
CommunicationStore com = subscribers[ipAddress];
if (((ICommunicationObject)com.NotifyCallback).State == CommunicationState.Opened)
{
try
{
//fires the callback method
com.NotifyCallback.Disconnecting();
com.IService.IncomingChannels.FirstOrDefault().Close();
}
catch (Exception)
{
throw;
}
}
}
}
}
public class CommunicationStore
{
public InstanceContext IService { get; set; }
public INotifyClientCallback NotifyCallback { get; set; }
}

WCF: calling self-hosted service from client callback handler

Problem:
getting a deadlock exception message in the WCF client.
Scenario:
Service calls a client callback (this call is completely independent and is initiated by some condition on the server).
While inside the client callback function, the client calls a function in the service and that's when the deadlock exception is thrown:
This operation would deadlock because the reply cannot be received until the current Message completes processing. If you want to allow out-of-order message processing, specify ConcurrencyMode of Reentrant or Multiple on CallbackBehaviorAttribute.
I tried to simplify the code as much as I can. I did read this article but still I cant find where the problem is: http://msdn.microsoft.com/en-us/library/cc294424.aspx
I'd appreciate any suggestions....
SERVICE:
[ServiceContract(Namespace = "http://abc.com/Core", SessionMode = SessionMode.Required, CallbackContract = typeof(ISvcCallback))]
public interface ISvc
{
// One way only - does not wait until operation completes and returns
// Can initiate session
[OperationContract(IsOneWay = true)]
void Initialize(string appId);
[OperationContract(IsInitiating = false)]
Account GetCurrentAccount();
}
public interface ISvcCallback
{
/// <summary>
/// Report status of the account
/// </summary>
/// <param name="acct"></param>
[OperationContract(IsOneWay=true)]
void AccountStatus(Account acct);
}
Service Implementation
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Reentrant, UseSynchronizationContext = false)]
public class Svc : ISvc
{
public Account GetCurrentAccount()
{
SipAccount sipAcct = null;
try
{
Account acct = m_MyBusinessObject.GetCurrentAccount();
}
catch (Exception ex)
{
}
return Acct;
}
}
}
CLIENT:
public class CallbackHandler : WcfSipItfService.IWinSipItfCallback
{
public void AccountStatus(Account Acct)
{
try
{
// display accout status in UI by delegate-wrapped event
// delegate and event declarations are somewhere else
// and work fine...
if (DisplayAccountStatusEvent != null)
DisplayAccountStatusEvent(Acct);
}
catch (Exception ex)
{
....
}
}
private void OnDisplayAccountStatusEvent(Account acct)
{
// call service function results in deadlock
Account acct = GetCurrentAccount();
}
}
The service is Duplex - uses WSDualHttpBinding.
The deadlock appears to be due to you making a new out bound call while processing a callback from the previous call.
The error message states that you may be able to solve it by "specify ConcurrencyMode of Reentrant or Multiple on CallbackBehaviorAttribute".
Edit
I missed the code that was off the screen. Couple of things to check:
Why do you need instance mode single?
Did you updated the service references after changing the concurrency mode?
What's your client? Is it a UI client? if so, you need to add callbackBehavior UseSynchronizationContext=false to client that implements callback contract.

How can a WCF Service Raise Events to its Clients?

I want to know is there way of Event Handling in WCF.
I came across Callbacks in WCF, but i want to do Event Handling in WCF.
My requirement is like i want to raise event to particular clients not to all the clients using Event Handling in WCF and i also want to maintain session.
I have seen Publisher/Subscriber model in WCF which deals with Callback , but this model publish to all the clients who have subscribed but i want to publish only to selected clients.
I think that can be done using Events in WCF.
Client side :
public class Callbacks : IServiceCallback
{
public void CallToMyClient(string name)
{
this.CallToMyClient(name);
}
}
protected void Page_Load(object sender, EventArgs e)
{
Callbacks callback = new Callbacks();
ServiceClient client = new ServiceClient(new InstanceContext(callback));
client.SubscribeClient();
client.DoSomeWork();
}
There is no Event in WCF to notify it's client but there is a callback channel, the purpose of the callback channel is same as event though the working principle is totally different in both cases.
To notify a particular client what you could do is store callback channel of that client while subscribing to somewhere, (I prefer Dictionary in this case). Later you can pick the instance and invoke your callback method over that channel, doing so only one client will get notified.
UPDATE
If you are interested here is the code:
public interface IClientCallback
{
//Your callback method
[OperationContract(IsOneWay = true)]
void CallToMyClient(string name);
}
[ServiceContract(CallbackContract = typeof(IClientCallback))]
public interface ITestService
{
[OperationContract(IsOneWay = true)]
void SubscribeClient();
[OperationContract(IsOneWay = true)]
void DoSomeWork();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Reentrant)]
public class ServiceImplementation : ITestService
{
private static readonly List<IClientCallback> CallbackChannels = new List<IClientCallback>();
/// <summary>
/// client should call this method before being notified to some event
/// </summary>
public void SubscribeClient()
{
var channel = OperationContext.Current.GetCallbackChannel<IClientCallback>();
if (!CallbackChannels.Contains(channel)) //if CallbackChannels not contain current one.
{
CallbackChannels.Add(channel);
}
}
public void DoSomeWork()
{
//Here write your code to do some actual work
//After you done with your work notify client
//here you are calling only the first client that is registered
IClientCallback callbackChannel = CallbackChannels[0];
callbackChannel.CallToMyClient("You are the only one receving this message");
}
}
WCF Duple Operation and UI Threads By jeff.barnes
Perhaps this can help you.
The WCF doesn't support event handler. Callback channel is the way for it
If you are using WCF for RPC(as apposed to web service or rest) you can use .Net Remoting to perfrom event invocation cross process.
You cannot use events. You can use callbacks to simulate events.

WCF InstanceContextMode.Multiple issues

So I'm hosting WCF service in a WinForms application. I have the following
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.PerCall)]
public class Test : ITest
{
public string TestIt(string input)
{
Thread.Sleep(5000);
return "test";
}
}
I'm using Named Pipes and have two instances of another application that act as clients to the above WCF service (running in a WinForms application). I thought based on the ConcurrencyMode setting of Multiple that when Client1 calls the Test Service, Client2 doesn't have to wait till the first call is complete. However, when Client1 calls TestIt, Client2 blocks until the call from Client1 is complete!?!?! Shouldn't it make a new instance each time based on the above settings?
Also, is the best way to keep a WinForms application that is hosting a WCF service responsive is by running the WCF service on a separate thread?
NOTE: Setting [CallbackBehavior(UseSynchronizationContext = false)] on the Test class does not alleviate the problem. The service still only responds to one request at a time.
Sounds like you want to set this
http://msdn.microsoft.com/en-us/library/system.servicemodel.servicebehaviorattribute.usesynchronizationcontext.aspx
to false. By default, if there is a synchronization context when service.Open() happens, WCF will pick it up and use it. But if you don't want that feature, this flag is how to turn it off.
After digging into this a bit more the only way I was able to get this to work properly was to start the ServiceHost on a separate thread in the WinForms application. If you don't do that setting the ConcurrencyMode and InstanceContextMode attributes does nothing.
I had the same problem.
My class that implemented Callback also contained methods for wcf client, so when I was calling some method from remote service and service was calling Callback method, I was creating a deadlock.
[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class AppContext : ICustomerOrderCallback
{
//WCF Proxy client
private CustomerOrderClient _client = null;
public AppContext()
{
InstanceContext context = new InstanceContext(this);
_client = new CustomerOrderClient(context);
_client.Subscribe(); //Remote method for subscribing callback
}
public void SendMessage(string message)
{
//Calling Remote method
_client.SendMessage(message);
}
//....code
//callback method
public void OnMessageReceived(string message)
{
//.....code
}
}
So I created a separate class for callback, added attribute CallBehavior to it and everything worked OK.
public class AppContext
{
private CustomerOrderClient _client = null;
private MyCallbackClass _myCallback = null;
public AppContext()
{
_myCallback = new MyCallbackClass();
InstanceContext context = new InstanceContext(_myCallback);
_client = new CustomerOrderClient(context);
_client.Subscribe();
}
public void SendMessage(string message)
{
_client.SendMessage(message);
}
}
[CallbackBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class MyCallbackClass : ICustomerOrderCallback
{
public void OnMessageReceived(string message)
{
//.....code
}
}