WCF wsHttpBinding and BasicHttpBinding in same WCF Service Application - wcf

I have been told that wsHttpBinding does not support older clients that still need to use older version of SOAP. I want to add a BasicHttpBinding endpoint in the same WCF Service Application so that clients can use either endpoint depending on their technology they are running. I am confused as to what the address to use for each of them. The default wsHttpBinding has no address set. What should the address be for BasicHttpBinding endpoint? Shouldn't the address for the wsHttpBinding be (for my example) http://localhost/WcfService1/Service1.svc ?

There's two things you need to consider here:
if your hosting in IIS (or WAS as part of IIS7), you cannot set a base address - the base address for your service will be the virtual directory where the MyService.svc file lives. You can still set relative addresses, though
if you self-host, you typically will add base addresses in your config, so you can spare yourself having to spell out the entire address all the time (but you can - if you wish to do so).
So if you have your MyService.svc inside a virtual directory called MyApp on your localhost machine, and then use this config:
<service name="MyService" behaviorConfiguration="Default">
<endpoint
address="wsHttp"
binding="wsHttpBinding"
contract="IMyService" />
<endpoint
address="basic"
binding="basicHttpBinding"
contract="IMyService" />
</service>
then your "old-style" basicHttp service will be reachable at:
http://localhost/MyApp/MyService.svc/basic
and your new wsHttp driven service will be reachable at:
http://localhost/MyApp/MyService.svc/wsHttp
You can name those relative addresses (anything after .../MyApp/MyService.svc) anything you like - just make sure they're different from one another.
Hosting in IIS --> location (virtual directory) of your *.svc file becomes your base address.
If you self-host your service inside a console app or a Windows NT Service, you get to set your base addresses yourself:
<services>
<service name="MyService" behaviorConfiguration="Default">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8185/Services/" />
</baseAddresses>
</host>
</service>
</services>
Now in this case, your "old-style" basicHttp service will be reachable at:
http://localhost:8185/Services/basic
and your new wsHttp driven service will be reachable at:
http://localhost:8185/Services/wsHttp
You can define a base address for each of the transports, e.g. one for http://, one for net.tcp:// and so on.
And of course, if you really must, you can also define your complete addresses inside your <endpoint> element for each of the service endpoints - this gives you total flexibility (but only works in self-hosting scenarios).
Marc

In WCF you have a base address and an enpoint address, in your case you can do something like this:
<service name="WcfEndpoints.Service1" behaviorConfiguration="WcfEndpoints.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="new" binding="wsHttpBinding" contract="WcfEndpoints.IService1" />
<endpoint address="old" binding="basicHttpBinding" contract="WcfEndpoints.IService1" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
Note you will need additional work for the basicHttpBinding endpoint to work with older (asmx) clients
http://msdn.microsoft.com/en-us/library/ms751433.aspx

Related

Wcf bindings difference while hosting on windows azure

I have wcf service application which i host on IIS and runs very well.
now i need to transfer the services to windows azure where i host them into web role.
i am not sure but i have heard that there are different bindings for windows azure
example:
azure has different bindings equivalent to basicHttp,WebHttp.
can i know what exactly i need to do to achieve the same.
here is my current service configuration
<service behaviorConfiguration="mybehavior" name="***">
<endpoint address="mobile" behaviorConfiguration="web" binding="webHttpBinding"
contract="*" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://127.0.0.1:81/Mobile.svc" />
</baseAddresses>
</host>
</service>
what change does this need
Thanks
You can achieve your goal with web.config transofmrations (and here). The issue with Azure is that there is no localhost, nor 127.0.0.1 there (well, there might be, but nothing is being routed to that local loop address). All you have to do is to change the baseAddress.
In order to change the baseAddress you may do any of the following:
use web.config transofmrations and in your web.Release.config put your azure domain name in the base address (http://yourapp.cloudapp.net/, or your custom domain if you are using one)
programatically bind the wcf service using the DIP of the role instance (check this and that questions for more information)

How to use msmq between WCF Router and WCF Service hosted in a Windows Service

In my current system I have a router service and over a dozen (about half use msmq, rest use tcp) WCF services hosted via IIS. I've been tasked with moving all services except for the router to a windows service. This has been accomplished using the same configurations that were present using the IIS web.config file. Here is a snippet of the previous configs (public queue for service: myservices/wcfservice):
<!--Router Service web.config-->
<client>
<endpoint address="net.msmq://localhost/MyServices/WCFService.svc" binding="netMsmqBinding" contract="*" name="IWCFService_Msmq" />
</client>
<!--Services web.config-->
<service behaviorConfiguration="SomeServiceBehavior" name="WCFService">
<endpoint binding="netMsmqBinding" name="IWCFService_Msmq"
contract="IWCFService" />
<host>
<baseAddresses>
<add baseAddress="net.msmq://localhost/MyServices/WCFService" />
</baseAddresses>
</host>
</service>
I'm confused as to why this works, as the service has a net.tcp binding and the router has msmq, and when I asked around, I was told it was "magic." I tried to do the same thing with my setup (router to windows service) using a similar configuration but get an error message:
<!--Router Service web.config-->
<client>
<endpoint address="net.msmq://localhost/MyServices/WCFService" binding="netMsmqBinding" contract="*" name="IWCFService_Msmq" />
</client>
<!--One "other" Services hosted in Windows Service app.config-->
<service behaviorConfiguration="SomeServiceBehavior" name="WCFService">
<endpoint binding="netMsmqBinding" name="IWCFService_Msmq"
contract="IWCFService" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost/MyServices/WCFService" />
</baseAddresses>
</host>
</service>
This has worked fine with all my services that are just using tcp, but when I try this with msmq and attempt to start the windows service, I get the following error in the Event Viewer:
Service cannot be started. System.InvalidOperationException: Could not find a base address that matches scheme net.msmq for the endpoint with binding NetMsmqBinding. Registered base address schemes are [net.tcp].
I'm new to msmq, so any help with be appreciated. Thanks!
Updated:
I've updated the base address in the service app.config to match the address that is in the router web.config. I tried this previously and it didn't work. I later found out it was because I didn't make the msmq itself a "Transactional Queue" (which was needed for our setup). Once this was done, everything worked out!
<!--One "other" Services hosted in Windows Service app.config-->
<service behaviorConfiguration="SomeServiceBehavior" name="WCFService">
<endpoint binding="netMsmqBinding" name="IWCFService_Msmq"
contract="IWCFService" />
<host>
<baseAddresses>
<add baseAddress="net.msmq://localhost/MyServices/WCFService" />
</baseAddresses>
</host>
</service>
Judging by the error message of the InvalidOperationException, it looks like "net.tcp" is the only enabled protocol in the Advanced Settings of your application hosted in IIS.
Is "net.msmq" an enabled protocol?
Open IIS Manager
Select your application
Click Advanced Settings in the Actions list
Add "net.msmq" to Behavior - Enabled Protocols
Why not give all of your MSMQ services their own config and all the tcp services their own? The issue is obviously it looks for a base address when you choose the binding to be msmq, and it can't find an msmq binding because all you've provided is a tcp base address binding. You can also of course add another base address that uses net.msmq inside the baseaddresses node.

wcf endpoint relative address

I'm just learning wcf and can't understand one very basic thing.
I'm creating a WCF service which I want to be hosted in IIS just like web application with it's own path like http://myhost/myapp/ and everything.
I'm creating the WCF service project in VS, I've got an *.svc file describing it, then I define a simple endpoint to it like that:
<endpoint address=""
binding="basicHttpBinding"
contract="wcf_service_auth.IPshService" />
Then I publish this service like an IIS web application to a virtual directory, let's assume it's name psh_pub, so I can access the service via url http://localhost/psh_pub/pshservice.svc/. It shows me WCF greetings page and gives me a link to WSDL, which gives me correct wsdl description.
That's ok.
The next step - I want to add a MEX endpoint. I add to config:
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange"/>
That's ok too, the endpoint is accessible at address http://localhost/psh_pub/pshservice.svc/mex and WcfTestClient.exe gives me correct config from that url.
Here the problem comes.
I have a WCF service working under IIS and I want to add one more endpoint to it. For example let it be a net.tcp endpoint. The IIS is configured by default to accept net.tcp connections at port 808 and I'm adding net.tcp protocol to properties of my web app, and I want to add an endpoint to my service like that:
<endpoint address=""
binding="netTcpBinding"
contract="wcf_service_auth.IPshService" />
and now I assume that my service should be accessible via the url net.tcp://localhost:808/psh_pub/pshservice.svc. But it's not. And every "how-to" and manual on the web tells that I should specify full address in the config file like that:
<endpoint address="net.tcp://localhost:808/psh_pub/pshservice.svc"
binding="netTcpBinding"
contract="wcf_service_auth.IPshService" />
And if I do so, it works. But if host the service in another virtual directory, I'll need to change the config. If I host it on the other server, I'll need to change config. If I host it on multiple servers, I'll have to maintain as many configs as servers I have.
So the main questions is:
Is there any way in WCF to specify a net.tcp (or https) endpoint of a IIS-hosted WCF service without specifying absolute url for it?
You should be able to define a base address for your net.tcp service endpoints:
<service name="YourServiceName">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:808/psh_pub/" />
</baseAddresses>
</host>
Then you should be able to use relative addresses in your actual endpoints:
<endpoint name="Tcp01"
address="pshservice.svc"
binding="netTcpBinding"
contract="wcf_service_auth.IPshService" />
</service>
WCF file-less activation (.Net 4.0) will let you register under a relative virtual path using the relativeAddress attribute:
<system.serviceModel>
<serviceHostingEnvironment>
<serviceActivations>
<add relativeAddress="relative-virtual-path/yourservice.svc"
service="YourServiceImpl" />
</serviceActivations>
</serviceHostingEnvironment>
</system.serviceModel>
relative to the base address of the Web application
This link talks about it: http://msdn.microsoft.com/en-us/library/ee354381.aspx

Multiple WCF service of the same service and contract type

Is it possible to host 2 WCF services of the same type and contract on the same AppDomain?
In the configuration below, I am configuring a single service of type Service.SomeService that implements contract ISomeService. what I want to do is be able to host 2 services of this type, of course with different URIs.
<system.serviceModel>
<services>
<service name="Service.SomeService">
<endpoint address="net.tcp://localhost:8000/SomeService"
binding="netTcpBinding"
contract="Service.ISomeService" />
</service>
</services>
I am also self hosting these services in a windows service.
Thanks.
Yes, a Windows Service can host Multiple WCF Services. Each WCF service must have a unique address however. When you add endpoints to a ServiceHost instance, you must specify a unique address for each end point, which means you must vary atleast one of the scheme (net.tcp, net.pipe, http, etc), domain, port or path.
So basically I should be able to do this by adding multiple endpoints to a service:
<services>
<service name="Service.SomeService">
<endpoint address="net.tcp://localhost:8000/SomeService1"
binding="netTcpBinding"
contract="Service.ISomeService" />
<endpoint address="net.tcp://localhost:8000/SomeService2"
binding="netTcpBinding"
contract="Service.ISomeService" />
</service>
I appears that service type and contract in the configuration file should be unique. But is it possible to instead add 2 services of the same type and contract instead of adding 2 endpoints to the same service?
I appears that service type and
contract in the configuration file
should be unique.
Why? They don't have to be unique - no way. What has to be unique is the address (the complete one) for the service endpoint - of course, how else would WCF know where to send certain requests?
But is it possible to instead add 2
services of the same type and contract
instead of adding 2 endpoints to the
same service?
Sure, no problem:
<services>
<service name="Service.SomeService">
<endpoint address="net.tcp://localhost:8000/SomeService1"
binding="netTcpBinding"
contract="Service.ISomeService" />
</service>
<service name="Service.SomeOtherService">
<endpoint address="net.tcp://localhost:8000/SomeService2"
binding="netTcpBinding"
contract="Service.ISomeOtherService" />
</service>
</services>

Hosting WCF service in IIS 7 (WAS) with net.tcp binding on TWO tcp ports

By default IIS 7 Web site has net.tcp binding with "808:" binding information string. If i add another net.tcp binding with "xxx:" exception occurs:
This collection already contains an address with scheme net.tcp. There can be at most one address per scheme in this collection.
Parameter name: item
How can i solve this problem and listen my service at TWO ports?
Basically, in your service, you should be able to define any number of service endpoints on any number of ports.
There's two ways to do this:
define a base address and a relative address in your service endpoint
define the full address in each endpoint
If you do option #1, you'll have something like this:
<service name="YourService">
<host>
<baseAddresses>
<add baseAddress="net.tcp://YourServer:5151/Services" />
</baseAddresses>
</host>
<endpoint name="endpoint1"
address="Service1"
binding="netTcpBinding"
contract="IYourService" />
<endpoint name="endpoint2"
address="Service2"
binding="netTcpBinding"
contract="IYourService" />
</service>
So in this case, you have two service endpoints for the same contract, and they'll be listening on URLs
net.tcp://YourServer:5151/Services/Service1
and
net.tcp://YourServer:5151/Services/Service2
You can have mulitple service endpoints, but only one base address.
The other option is to specify no base addresses and specify your full service address in the endpoint directly:
<service name="YourService">
<endpoint name="endpoint1"
address="net.tcp://YourServer:5151/Services/Service1"
binding="netTcpBinding"
contract="IYourService" />
<endpoint name="endpoint2"
address="net.tcp://YourServer:6868/Services/Service2"
binding="netTcpBinding"
contract="IYourService" />
</service>
In this case, since you're defining the whole address in the endpoint, you can pick two different TCP ports, one for each endpoint. This should work with no problem at all. You have two separate endpoints on two separate ports, both listening and being serviced by the same service class in the background.
Marc
I was trying to deply a WCF service to one of my web servers the other day and ran into a problem. I kept getting the following error message:p>
This collection already contains an address with scheme http. There can be at most one address per scheme in this collection.Parameter name: item
The problem didn't happen on my local machine but did on the web server making it a little difficult to figure out what was causing it. It happened on the server because my web server is in a shared hosting environment in which case the WCF service also needs to know the host header. To do this I navigated to in the web.config and added the following:
<serviceHostingEnvironment>
<baseAddressPrefixFilters>
<add prefix=http://MyHostHeader />
</baseAddressPrefixFilters>
</serviceHostingEnvironment>
Its me again.
This works with self host
<baseAddresses>
<add baseAddress="net.tcp://localhost" />
<add baseAddress="net.tcp://localhost:12345" />
</baseAddresses>
but with IIS7+WAS cause exception
Could not connect to net.tcp://localhost:12345/game2.svc. The connection attempt lasted for a time span of 00:00:02.0936160. TCP error code 10061: No connection could be made because the target machine actively refused it 127.0.0.1:12345.
The question was about IIS hosting environment