I am trying to implement a C# WCF server to the ONVIF specifications at http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl. I have generated the contract code using
SvcUtil.exe http://www.onvif.org/onvif/ver20/ptz/wsdl/ptz.wsdl http://www.onvif.org/onvif/ver10/device/wsdl/devicemgmt.wsdl
which generates Device and PTZ interfaces. I then created an implementation of the generated interfaces and expose that using a ServiceHost like this:
serviceHost = new ServiceHost(typeof(OnvifImpl), baseUri);
serviceHost.AddServiceEndpoint(typeof(Device), new WSHttpBinding(), "device_service");
serviceHost.AddServiceEndpoint(typeof(PTZ), new WSHttpBinding(), "ptz");
When I point Onvif Device Manager 2.2.250 (https://sourceforge.net/projects/onvifdm/) at my server, I get an exception in my server "The SOAP action specified on the message, '', does not match the HTTP SOAP Action, 'http://www.onvif.org/ver10/device/wsdl/GetScopes'.". Wireshark shows that the request does not have any SOAP header. However, as far as I can tell, the client was developed against the same WSDL files.
I am afraid I am completely new to ONVIF, SOAP, Web services and WCF, so I have no idea where the problem may be. I have seen various suggestions to modify the client, but that is not an option.
The answer is to use a custom binding to remove WS-Addressing. This is what the client code does, so I do the same to match. I am not entirely sure whether this is a "solution" or a "workaround" but it get the two talking.
var binding = new CustomBinding(new BindingElement[] {
new TextMessageEncodingBindingElement(MessageVersion.Soap12, Encoding.UTF8),
new HttpTransportBindingElement(),
});
serviceHost.AddServiceEndpoint(typeof(Device), binding, "device_service");
serviceHost.AddServiceEndpoint(typeof(PTZ), binding, "ptz");
The key difference is using MessageVersion.Soap12 instead of MessageVersion.Soap12WSAddressing10 which is the default.
Related
How to register client on server to listen some change? I want to notify my client and send some data when something changed on my server. Also, I use NetTcpBinding. I tried many examples, but I can't get method from server to register in. I don't have any config file.
Thanks in advance.
There is example of registering client on server.
ChannelFactory<ITrending> factory = new ChannelFactory<ITrending>(
new NetTcpBinding(), new EndpointAddress(#"net.tcp://localhost:6000/ITrending"));
proxy = factory.CreateChannel();
You can use the CallBack functionality in WCF services , it can be used for sending the changes in any entity or object value. In this case, Client must act as a server and server as a Client to receive the updates based on the method in the Client which is receiving the changes.
More detailed explanation : http://www.dotnetcurry.com/wcf/721/push-data-wcf-callback-service
I'm attempting to set up a client (Web Application) and service (WCF Service) that will communicate using a WSHttpBinding. It appears that in order to use this binding the client sends preliminary messages to set up the channel.
Between the client and the service exists a service bus which is routing on a custom header. The message, when using BasicHttpBinding security, routes without issue.
My question is: Is there any way to add the same custom header to the preliminary RequestSecurityToken message?
Thank you in advance.
This has been resolved.
Unfortunately, according to the MSDN documentation, a service using WCF transport security cannot go through a router, nor should either, service nor client, be located on the internet (https://msdn.microsoft.com/en-us/library/ff648863.aspx#TransportSecurity).
We wanted to violate both 'principles'.
So in order to cut down the messages, from five calls and responses to one, we switched to Message Security and turned off EstablishSecurityContext and NegotiateServiceCredential. - This had to be done on both the Service and Client configuration settings.
In addition to this, a noteworthy tip may be that, in order to point the service to our service bus, we changed theClientViaBehavior of the service on the Client Side.
Turn off EstablishContext and NegotiateServiceCredential:
WSHttpBinding binding = new WSHttpBinding();
binding.Security.Mode = SecurityMode.Message;
binding.Security.Message.EstablishSecurityContext = false;
binding.Security.Message.NegotiateServiceCredential = false;
Point client to Service Bus:
serviceClient.Endpoint.EndpointBehaviors.Add(new ClientViaBehavior(new Uri("http://url/WCFService/ServiceName.svc")));
I've found myself in need of finding a WCF Binding that uses HTTPS/SOAP and must be duplex. I was programmatically using NetTcpBinding before but the binding now has to be HTTPS/SOAP. I did some research and it seems like it's not possible without creating your own CustomBinding.
However I'm sort of at a lost in what to do (not very familiar with bindings and the setup). I can't seem to get correct binding elements for what I need:
public class CustomHttpsBinding : CustomBinding
{
public CustomHttpsBinding()
{
}
public override BindingElementCollection CreateBindingElements()
{
ReliableSessionBindingElement https = new ReliableSessionBindingElement();
SecurityBindingElement security = SecurityBindingElement.CreateCertificateOverTransportBindingElement();
CompositeDuplexBindingElement duplex = new CompositeDuplexBindingElement();
SslStreamSecurityBindingElement ssl = new SslStreamSecurityBindingElement();
MessageEncodingBindingElement encoding = new GZipMessageEncodingBindingElement((MessageEncodingBindingElement) new BinaryMessageEncodingBindingElement());
HttpsTransportBindingElement transport = new HttpsTransportBindingElement();
return new BindingElementCollection(new BindingElement[] { https, security, duplex, ssl, encoding, transport });
}
It gives me an invalid operation exception when checking soap over secure transport requirements saying my contract is configured with an authentication mode that requires integrity and confidentiality. However the transport cannot provide integrity and confidentiality.
Seems like my HttpsTransportBindingElement is not correct? I'm not sure.
Thanks
edit:
I did manage to get WSDualHttpBinding to work at one point, but it seems like HTTPS is not possible with it (as well as others on the internet which say it shouldn't even be used)
HTTP isn't duplex protocol - its request / response - that's why wsDualHttpBinding uses two connections - one in each direction. Silverlight achieves duplex over HTTP by polling for messages from the client under the covers
NetTcpBinding uses TCP which can quite happily be duplex
If you can wait until 4.5 is released later this year this has the NetHttpBinding which does duplex using the WebSocket protocol
WCF newbie here... I'm trying to self-host a WCF service using NetTcpBinding. Based on the MSDN "how-to" tutorial I have done all the binding in code, which I then changed from WsHttpBinding to NetTcpBinding, and now looks like this:
var baseAddress = new Uri("net.tcp://localhost:8000/MyWebService");
var selfHost = new ServiceHost(typeof(ConcreteWebService), baseAddress);
try {
var binding = new NetTcpBinding();
binding.Security.Mode = SecurityMode.Message;
selfHost.AddServiceEndpoint(typeof(IWebService), binding, "TRWebService");
selfHost.Open();
Console.WriteLine("The service is ready at {0}", baseAddress.AbsoluteUri);
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
selfHost.Close();
} catch (CommunicationException ce) {
Console.WriteLine("An exception occurred: {0}", ce.Message);
selfHost.Abort();
}
Thing is, the tutorial then says you have to run svcutil.exe to generate a proxy for the client... but since I switched to NetTcpBinding, svcutil doesn't work anymore - can't detect my service. I googled the issue, and found that every single example out there of NetTcpBinding does the setup in the app.config file, not in code, and they all add an endpoint called "Mex", with binding type of "mexTcpBinding". There doesn't appear to be any equivalent of this in code.
So, do I have to change my project to use app.config, and abandon the code-based approach? Can anyone explain to me what Mex is, why I need it, and why it (apparently) can't be called in code - or if it can, how, or why is it discouraged? In general, when is it better to use app.config, and when code for WCF services?
If you use netTcpBinding - and in a "behind-the-corporate-firewall" LAN environment, it's definitely a great idea to do so - you need to also expose a MEX endpoint (Metadata Exchange) using the mexTcpBinding in order for svcutil to be able to detect and find that service.
MEX = Metadata Exchange is the mechanism that WCF uses to "publicly advertise" what a service looks like. If you have a MEX endpoint, then utilities like svcutil can query and "discover" a service, e.g. find out about all the service methods it exposes, about the parameters it expects to get and so on.
To add a MEX endpoint, you can definitely use code, too! Something like this fragment:
var mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
selfHost.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, "mex");
Without MEX, you need to somehow "tell" the client trying to consume your service what it is your service offers so that the client can make sure to call the proper methods with the proper parameters.
I am just getting started with WCF and would like to set up a distributable networked system as follows: (but am not sure if it is possible.)
I have a .net client that has business logic. It will need various data from various sources so I would like to add a 'server' that contains an in-memory cache but also WCF capabilities to send/receive and publish/subscribe from data sources for data that is not cached. I think it should be possible for these server applications to be identical in terms of code, but highly configurable so that requests could be dealt with in a peer to peer fashion, or traditional client-server as required. I think it could be done so that essentially a server sends a request to wherever it has the endpoint configured and gets a response.
Essentially a server would be configured as below:
Server A
========
Operation 1 - Endpoint I
Operation 2 - Endpoint II
Server B
========
Operation 1 - Endpoint IV
Operation 2 - Endpoint III
The configuration would be stored for each server in app.config and loaded into memory at startup. So each WCF operation would have its own WCF config (in terms of endpoints etc.) and it would send particular requests to different places according to that configuration.
From what I have read of WCF I think this is possible. I don't know have enough experience to know if this is a standard WCF pattern that I am describing (if so please let me know). Otherwise, my main question is, how do I programatically configure each operation (as above) in WCF?
Please let me know if I have not explained myself clearly.
Thanks in advance for any help,
Will
I don't know if this exactly will get you what you are looking for, but I this is what I use to add my WCF endpoints to my Windows Service. This is the code that the service runs to load all the wcf services:
IDictionary<string, ServiceHost> hosts;
NetTcpBinding binding;
CustomBinding mexBinding;
private void AddService(Type serviceImp, Type serviceDef, string serviceName)
{
ServiceHost host = new ServiceHost(serviceImp);
string address = String.Format(baseAddress, wcfPort, serviceName);
string endAdd = address;
string mexAdd = address + "/mex";
ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();
host.Description.Behaviors.Add(behavior);
host.AddServiceEndpoint(serviceDef, binding, endAdd);
host.AddServiceEndpoint(typeof(IMetadataExchange), mexBinding, mexAdd);
host.Open();
hosts.Add(serviceDef.Name, host);
}
There's a baseAddress string that I didn't copy in, but it just has the net.tcp address for the endpoint. Likewise for the wcfPort. Different baseAddresses and ports are used for debug, testing and production.
Just in case it isn't clear, serviceImp is the service implementation and serviceDef is the interface that defines the contract. Hope this helps.
EDIT - Here are some references I used to help me figure all of this stuff out:
Creating WCF Service Host Programmatically
Net.Tcp Port Sharing Sample, Part 2
Service Station: WCF Addressing In Depth
As far as I know you can't specify configuration on per operation basis. The lowest level is the interface level. The simplest (ugly) solution would be to put each operation in a separate interface.
Putting each operation in a separate interface is a valid and good design approach. Agatha Request/Response Layer follows this approach. Have a look at this and this is pretty useful and extensible
http://code.google.com/p/agatha-rrsl/