WCF - remote service without using IIS - base address? - wcf

I'm trying to get my head around the addressing of WCF services.
We have a client-server setup where the server occasionally (maybe once a day) needs to push data to each client. I want to have a lightweight WCF listener service on each client hosted in an NT service to receive that data. We already have such an NT service setup hosting some local WCF services for other tasks so the overhead of this is minimal.
Because of existing legacy code on the server I believe the service needs to be exposed as ASMX and use basicHttpBinding to allow it to connect.
Each client is registered on the server by the user (they need to configure them individually) so discovery is not the issue.
My question is, how does the addressing work? I imagine the user entering the client's address on the server in the form
http://0.0.0.0/MyService
or even
http://hostname/MyService
If so, how do I configure the client service in its App.config? Do I use localhost?
If not then what is the reccommended way of exposing the service to the server?
Note:
I don't want to host in IIS as that adds extra requirements to the hardware required for the client.
The clients will be almost certainly located on LANs, not over the public internet

You configure the base address of the service like so:
<system.serviceModel>
<services>
<service name="Ns.FooService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9999" />
</baseAddresses>
</host>
<endpoint
address="/foo"
binding="basicHttpBinding"
contract="Ns.IFooContract" />
</service>
</services>
</system.serviceModel>
And then your service could be accessible through http://servename:9999/foo. You may take a look at this article for more information.

Related

how does my net.tcp wcf services work without specifying PortSharingEnabled in the binding?

I read all over the msdn where it says to enable port sharing : The port sharing service should be started and my net.tcp binding should specify 'portSharingEnabled = True'.
I also see that net.tcp binding documentation shows the default value for portsharing as false.
But in my VS 2013, WIN 7 machine, I have a console app hositing many services and I am able to run it from VS without any issues. My servichost is able to host more than 10 services with the same port. What am I missing to understand ? Any ideas ?
I use this endpoint followed by servicename for all my services:
<service name="Lookup" behaviorConfiguration="">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8000/"/>
</baseAddresses>
</host>
<endpoint
name="IEntitiesLookup"
binding="netTcpBinding"
address="LookupService"
contract="ILookup" />
</service>
I managed to clear my understanding on port sharing to an extent. But would be happy for more thoughts on this.
I managed to find the reason behind the above scenario. Within a process, I am able to host several endpoints which shares the same port. This does not need port sharing to be enabled. But if I have another process which tries to host some services with same port numbers, then an exception for 'ports already in use' happens. In this case, we then need to enable port sharing in the binding of all the endpoints in both the service host processes and start the PortSharing service.
I believe this boils down to the understanding that in the transport layer, the port numbers are tied to the process.

WCF Routing backup list in client

Is it possible to define a WCF backup list in a client, so that a single-point-of-contact routing service is not nessasary?
I have two services implementing the same contact (interface). If the first service is not avaliable I would like the client to know that the backup service is to be used.
Is this possible or do I have to create a routing service (single-point-of-contact) that the client would communication with?
<client>
<endpoint address="http://localhost:49192/OrdinaryCustomerService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ICustomer"
contract="OrdinaryCustomerServiceReference.ICustomer" name="OrdinaryCustomerService" />
<endpoint address="http://localhost:49860/PremiumCustomerService.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_ICustomer"
contract="PremiumCustomerServiceReference.ICustomer" name="PremiumCustomerService" />
</client>
<routing>
<backupLists>
<backupList name="CustomerBackupList">
<add endpointName="PremiumCustomerService"/>
</backupList>
</backupLists>
</routing>
Just an idea but i have a similar issue and i have been thinking about creating a routing service on the client (IIS webserver in my case) so that all request on the webserver can fail over to different web services. We also have multiple webservers for fail over so i would put a router on each.
Not ideal but best solution i have found so far. If the router on the IIS box goes down chances are the IIS will be down as well and therefore our system would have kicked over tot he other webserver anyway.
We also have proper wfc routers with backup for our middle teir but before it was a manual change to the webservice to handle this.

How to configure WCF with NO security, and most minimal bindings

I've been having major problems with WCF, which are not amenable to any wisdom I can find. I've tried basicHttpBinding, wsHttpBinding, netTcpBinding (with the Net.Tcp service running on both machines). The behaviour can be boiled down to:
works on same machine, when running in debugger, standalone (non-service) process, Windows service
cannot be accessed from other machine, unless I'm running the service in the debugger
I must confess to being baffled by the plethora of options for bindings/security/etc. I must also confess to being ignorant of the restrictions on running as a Windows service, although I'm sure I've read somewhere that the SYSTEM account does not have network credentials. I've tried running the service under my own credentials, with the same results.
I'm up against a deadline in a few hours, and at the moment I'm going to have to resort to running as a standalone process, which is pretty embarassing.
I'm sure I've made some simple but crucial mistake in my understanding, and would be happy to be enlightened. But for now I'd be happy if someone knows a quick and dirty way to run WCF between two machines on the same Windows network without any security necessary, where one is a windows service and the other is a Windows GUI app.
This calls for the NetNamedPipe binding (on-machine communication)!
Your config would have to look something like:
<system.serviceModel>
<bindings>
<netNamedPipeBinding>
<binding name="NoSecurityIPC">
<security mode="None" />
</binding>
</netNamedPipeBinding>
</bindings>
<client>
<endpoint name="internal"
address="channel1"
binding="netNamedPipeBinding"
bindingConfiguration="NoSecurityIPC"
contract="IYourService" />
</client>
<services>
<service name="Namespace.YourService">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/" />
</baseAddresses>
</host>
<endpoint
address="channel1"
binding="netNamedPipeBinding"
bindingConfiguration="NoSecurityIPC"
contract="IYourService" />
</service>
</services>
</system.serviceModel>
Marc
Is it a Windows Firewall issue? BasicHttpBinding defaults to security mode "none", and setting it on netTcp for client and service is as simple as putting a security mode="none" element under the root binding element in both the client and server config. Seems like the firewall on the server would be the only thing that'd keep you from connecting if the security mode is set to none.
1) as well as opening the firewall, you almost certainly need to explicitly permit binding the serving port via the APIs on HTTP.SYS. This can be done by the built in netsh http add command on Vista or later, via the downloadable httpcfg tool on earlier systems, or by directly P/Invoking against the HTTP APIs with administrative privilege as a set-up step.
2) if you have multiple services, getting them to share the address space on a given port is far easier if they talk HTTP than net.tcp
3) as a default, a service that talks across the network should be run with Network Service identity, ideally as a service-specific SID : even if the data are not sensitive, exposing a high privilege user like System on the network is not good practice.

WCF Client configuration - base address?

I'm connecting a WCF client to a group of services all implementing the same contract and all at the same host. I was hoping that there would be a way to combine the endpoint definitions to cut down on configuration clutter. I also would rather not do it programmaticly - just by configuration. Right now, my config has this repeated many times:
<endpoint address="http://hostname/ServiceA.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_MyBinding"
contract="ServiceReference.ISearchService" name="ServiceA">
</endpoint>
<endpoint address="http://hostname/ServiceB.svc"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_MyBinding"
contract="ServiceReference.ISearchService" name="ServiceB">
</endpoint>
// continued for ServiceC, ServiceD, etc
For server configurations, there is some notion of "baseAddressPrefixFilters" that can be used for this purpose - is there anything for client configuration?
There is the concept of a base address in WCF - unfortunately, that only works if you self-host, e.g. host your service in a console app or NT service. However, that only works on the server side - there's nothing similar on the client side. On the client side, you always have to define the complete, full service address your endpoint should connect to.
If you host in IIS, your service address is determined by the server name, the virtual directory (and possibly subdirectories under that) and the name of the *.svc file used to host the service in IIS. This is a fixed system convention and you cannot influence it, unfortunately (.NET 4 will bring some remedy to that).

The request for security token could not be satisfied because authentication failed

This is a bit different than other questions I've found on SO regarding this issue...
We're running 2 websites, one a WCF service and the other is a client to the service. Whenever we try to access the service we get the message "The request for security token could not be satisfied because authentication failed."
Both the websites are hosted on the same machine and under the same App Pool. Both websites are hosted on port 80 and have different host headers... example: client.website.com and service.website.com
We're using wsHttpBinding on the service side:
<endpoint address="http://service.website.com/MessagingService.svc/wshttp"
binding="wsHttpBinding"
contract="WebServices.IMessagingService"
bindingNamespace="CNI/CNIMessenger"
bindingConfiguration="wsHttpBindingConfig"
name="wsHttpBinding">
</endpoint>
When we try to run the service we get the above mentioned error. After hours of debugging I was able to find that if I use a service configuration address without any url only wshttp and point my client to the IP Address/Port everything works fine. for example:
<endpoint address="wshttp"
... And client address points to: http://127.0.0.1:8888/MessagingService.svc/wshttp
When I change the address and website to use service.website.com and keep the port 8888 I continue to get the same error.
Does anyone have any insight on this? MANY Thanks!
Try adding the following to your configuration:
<host>
<baseAddresses>
<add baseAddress="http://service.website.com"/>
</baseAddresses>
</host>
keep the address as wshttp