Hello all,
I'm a newbie on WCF. I'm able to build a self-hosted WCF service and 4 .NET applications connected to it using NetTcpBindings. Now I need one more client written in Python2.7 script to connect to this WCF service providing duplex communication.
What I have tried:
As far as I googled,
WsDualHttpBinding with
SOAP 1.2 should be used.
Here is my
service interface
namespace GPH_QuickMessageServiceLib
{
[ServiceContract(
Name = "GPH_QuickMessageService",
Namespace = "GPH_QuickMessageServiceLib",
SessionMode = SessionMode.Required,
CallbackContract = typeof(IMessageServiceCallback))]
public interface IMessageServiceInbound
{
[OperationContract]
[WebInvoke]
int JoinTheConversation(string userName);
[OperationContract]
[WebInvoke]
int LeaveTheConversation(string userName);
}
public interface IMessageServiceCallback
{
[OperationContract(IsOneWay = true)]
[WebInvoke]
void NotifyUserJoinedTheConversation(string userName, List<string> SubscriberList);
[OperationContract(IsOneWay = true)]
[WebInvoke]
void NotifyUserLeftTheConversation(string userName, List<string> SubscriberList);
}
}
Here is my
service behavior
namespace GPH_QuickMessageServiceLib
{
[ServiceBehavior(
ConcurrencyMode = ConcurrencyMode.Single,
InstanceContextMode = InstanceContextMode.PerCall)]
public class GPH_QuickMessageService : IMessageServiceInbound
{
private static List<IMessageServiceCallback> _callbackList = new List<IMessageServiceCallback>();
private static int _registeredUsers = 0;
private static List<string> SubscriberList = new List<string>();
private static Dictionary<string, IMessageServiceCallback> NotifyList = new Dictionary<string, IMessageServiceCallback>();
public GPH_QuickMessageService() { }
public int JoinTheConversation(string userName)
{
IMessageServiceCallback registeredUser = OperationContext.Current.GetCallbackChannel<IMessageServiceCallback>();
if (!_callbackList.Contains(registeredUser))
{
_callbackList.Add(registeredUser);
SubscriberList.Add(userName);
NotifyList.Add(userName, registeredUser);
}
_callbackList.ForEach(
delegate (IMessageServiceCallback callback)
{
callback.NotifyUserJoinedTheConversation(userName, SubscriberList);
_registeredUsers++;
});
return _registeredUsers;
}
public int LeaveTheConversation(string userName)
{
IMessageServiceCallback registeredUser = OperationContext.Current.GetCallbackChannel<IMessageServiceCallback>();
if (_callbackList.Contains(registeredUser))
{
_callbackList.Remove(registeredUser);
NotifyList.Remove(userName);
SubscriberList.Remove(userName);
_registeredUsers--;
}
_callbackList.ForEach(
delegate (IMessageServiceCallback callback)
{
callback.NotifyUserLeftTheConversation(userName, SubscriberList);
});
return _registeredUsers;
}
}
}
Here is my
App.config in
service-host application
="1.0"="utf-8"
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<system.serviceModel>
<services>
<service name="GPH_QuickMessageServiceLib.GPH_QuickMessageService"
behaviorConfiguration = "QuickMessageServiceMEXBehavior">
<endpoint address ="soap"
binding="wsDualHttpBinding"
contract="GPH_QuickMessageServiceLib.IMessageServiceInbound" />
<endpoint address ="service"
binding="netTcpBinding"
contract="GPH_QuickMessageServiceLib.IMessageServiceInbound" />
<endpoint address="mex"
binding="mexTcpBinding"
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:2709/GPH_QuickMessageService/soap"/>
<add baseAddress="net.tcp://localhost:8868/GPH_QuickMessageService"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="QuickMessageServiceMEXBehavior" >
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
And here is what I have in Python2.7 script (I'm using
suds-jurko 0.6 with a
hack to use SOAP 1.2 as .NET
wsDualHttpBinding only supports SOAP 1.2)
from suds.client import Client
from suds.bindings import binding
import logging
logging.basicConfig(level=logging.INFO)
logging.getLogger('suds.client').setLevel(logging.DEBUG)
binding.envns = ('SOAP-ENV', 'http://www.w3.org/2003/05/soap-envelope')
client = Client('http://localhost:2709/GPH_QuickMessageService/soap?wsdl',
headers={'Content-Type': 'application/soap+xml'})
result = client.service.JoinTheConversation('RIDE')
print client
print 'result = %s' % result
As i guess, my python client already bound to server and get the list of available operations but it could not get the result from those operations. It always returns None
C:\Python27\python.exe C:/Users/sev_user/PycharmProjects/WcfInteration/venv/Scripts/suds_client.py
DEBUG:suds.client:sending to (http://localhost:2709/GPH_QuickMessageService/soap/soap)
message:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:ns0="GPH_QuickMessageServiceLib" xmlns:ns1="http://www.w3.org/2003/05/soap-envelope" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENV="http://www.w3.org/2003/05/soap-envelope">
<SOAP-ENV:Header/>
<ns1:Body>
<ns0:JoinTheConversation>
<ns0:userName>RIDE</ns0:userName>
</ns0:JoinTheConversation>
</ns1:Body>
</SOAP-ENV:Envelope>
DEBUG:suds.client:headers = {'SOAPAction': '"GPH_QuickMessageServiceLib/GPH_QuickMessageService/JoinTheConversation"', 'Content-Type': 'application/soap+xml'}
Suds ( https://fedorahosted.org/suds/ ) version: 0.6
Service ( GPH_QuickMessageService ) tns="http://tempuri.org/"
Prefixes (3)
ns0 = "GPH_QuickMessageServiceLib"
ns1 = "http://schemas.microsoft.com/2003/10/Serialization/"
ns2 = "http://schemas.microsoft.com/2003/10/Serialization/Arrays"
Ports (2):
(WSDualHttpBinding_GPH_QuickMessageService)
Methods (7):
JoinTheConversation(xs:string userName)
LeaveTheConversation(xs:string userName)
NotifyUserJoinedTheConversation()
NotifyUserLeftTheConversation()
NotifyUserOfMessage()
ReceiveMessage(xs:string userName, ns2:ArrayOfstring addressList, xs:string userMessage)
sum(xs:int a, xs:int b)
Types (4):
ns2:ArrayOfstring
ns1:char
ns1:duration
ns1:guid
(NetTcpBinding_GPH_QuickMessageService)
Methods (7):
JoinTheConversation(xs:string userName)
LeaveTheConversation(xs:string userName)
NotifyUserJoinedTheConversation()
NotifyUserLeftTheConversation()
NotifyUserOfMessage()
ReceiveMessage(xs:string userName, ns2:ArrayOfstring addressList, xs:string userMessage)
sum(xs:int a, xs:int b)
Types (4):
ns2:ArrayOfstring
ns1:char
ns1:duration
ns1:guid
result = None
DEBUG:suds.client:HTTP succeeded:
Process finished with exit code 0
I have tried several ways other than suds, such as
ZSI,
zeep, but always get result as '
None' or '
0'. I have attached logger on these SOAP client process and always get either '
HTTP succeed' or '
202 Accepted'. Couldn't figure out myself what should be wrong here.
Did any body face the same problem? Please give me some clue to resolve this.
Or any other idea to get duplex communication between Python2.7 and WCF is always appreciated.