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.
Related
I'm approaching to WCF Service, starting with the tutorial provided by Microsoft. I created a very simple WCF Service (CalculatorService) and I've some doubts about the EndpointAddress of this service.
When I create the WCF Host, I set the Endpoint like this:
Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");
// Step 2 Create a ServiceHost instance
ServiceHost selfHost = new ServiceHost(typeof(Service1), baseAddress);
// Step 3 Add a service endpoint.
selfHost.AddServiceEndpoint(typeof(IService1), new WSHttpBinding(), "CalculatorService");
Everything works if I debug the entire solution, but, if I launch the WCFHost executing its .exe file, launching also the application of the Client gives me the following exception:
System.ServiceModel.EndpointNotFoundException: No endpoint listening in http://localhost:8732/Design_Time_Address/WcfServiceLibrary/Service1/.
The fact is that if I try to open a browser and search the address http://localhost:8000/GettingStarted/, I get correctly the page of the Service. I suppose that the Service is hosted at one address and the Client tries to access to it via a different one.
Could anyone help me to solve this issue?
If you have, in the client code, hard coded this address http://localhost:8732, then change it there. But your client is probably (you didn't put that info unfortunately in your question) automatically generated. In that case client config is in App.config file(if we are talking about your solution), and in config file of the .exe file when you build your project. You should look into your [ClientApplicationName].exe.config file and update the endpoint address to port 8000.
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.
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")));
How can i add wcf service at runtime in my winform UI.
I created a wcf service which return running processes of hosted machine. I want to add the hosted machine service in my winform application.
You need to change endpoints dynamically at runtime, so You need WCF Discovery.
Structure :
WCF Consumer(s) <---> WCF Discovery Service <---> WCF Service(s)
Implementation :
How to: Implement a Discovery Proxy
How to: Implement a Discoverable Service that Registers with the Discovery Proxy
How to: Implement a Client Application that Uses the Discovery Proxy to Find a Service
Topology :
Start Discovery Service [ Structure BackBone ]
Start Service(s) [ Every Service will ANNOUNCE its startup to the Discovery Service ]
Start Client(s) [ Every Client will DISCOVER ( FIND & RESOLVE ) Services' endpoints from the Discovery Service ]
Notes :
Discovery process uses UDP ( Check your Firewall, It can block connections )
Services MUST announce their startup, thus Self-Hosted services is OK, but IIS-Hosted 5/6 ones is NOT because they started automatically when 1st invoke happends !
Solving IIS-Hosted 5/6 Issue :
By Extending Hosting Using ServiceHostFactory
So that you can start your IIS-Hosted 5/6 services manually without being invoked for the first time
You can also use WCF Routing Service.
BROTHER TIP :
Don't go far for a Serverless ( No-BackBone, No-BootleNeck, Fully-Distributed, .. etc ) ideal topology, this'll blowup your head and got you crazy :D
For a beginner, I suggest you this tutorial [ WCF Tutorials ]
not sure what you are trying to do here. But you need to know two things to call the WCF service 1) Service Contract 2) End Point. Now there is no escaping from Service Contract as you need to know what all operations you can consume. However, with WCF 4 there is a new feature called WCF discovery which helps you determine the end point dynamically i.e. at RunTime. Refer to following link http://msdn.microsoft.com/en-us/library/dd456791.aspx
If I understand you question properly you need some code that will add service in run-time without using any configuration in *.config file and *.svc files.
See that sample:
Uri baseAddress = new Uri("http://localhost:8080/hello");
// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(HelloWorldService), baseAddress))
{
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Open the ServiceHost to start listening for messages. Since
// no endpoints are explicitly configured, the runtime will create
// one endpoint per base address for each service contract implemented
// by the service.
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
// Close the ServiceHost.
host.Close();
}
It creates self-hosted service in console app.
http://msdn.microsoft.com/en-us/library/ms731758.aspx
Is that what you asked?
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/