wcf endpoint relative address - wcf

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

Related

WCF proxy creation at client side with multiple endpoint

i have one service with two endpoint. one endpoint is for wsdual binding and another for tcp binding. when i start my wcf service with wcfsvchost.exe like
WcfSvcHost.exe /service:"C:
\Users\TRIDIP\Documents\Visual Studio 2010\Projects\BBAChatService\BBAChatService\bin
\BBAChatService.dll" /config:"C:\Users\TRIDIP\documents\visual studio 2010\Projects
\BBAChatService\BBAChatService\Web.config"
then my service was started.
the problem is when i try to create proxy at client side after starting service with WcfSvcHost.exe then all endpoints related info gets added in client's config file but i want that when i will create proxy with tcp mex endpoint or mexHttpBinding from client side then only valid endpoint should be added in client's config file not all endpoints. so guide me what to change in my config file at service end. here is my config file at service end....please have look.
<service name="BBAChatService.ChatService" behaviorConfiguration="BBAChatService.ChatServiceBehavior" >
<host>
<baseAddresses>
<add baseAddress ="http://localhost:8732/ChatService.svc/"/>
<add baseAddress ="net.tcp://localhost:7998/ChatService/"/>
</baseAddresses>
</host>
<endpoint name="dual_bind"
address="dual"
binding="wsDualHttpBinding"
bindingConfiguration="WSDualHttpBinding_IChatService"
contract="BBAChatService.IChatService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint name="tcp_bind"
address="tcp"
binding="netTcpBinding"
bindingConfiguration="tcpBinding"
contract="BBAChatService.IChatService">
</endpoint>
<endpoint address="net.tcp://localhost:7996/ChatService/mex"
binding="mexTcpBinding"
contract="IMetadataExchange"/>
</service>
guide me what to change in my config. thanks
If you expose multiple endpoints in the same service you have multiple ports in WSDL and svcutil (Add service reference) will import configuration for every offered port. WSDL always exposes all defined endpoints for the service and svcutil works with all of them.
You must either manually modify your client config to remove HTTP endpoint configuration on the client side or you must split your service to two different implementations each with single endpoint.

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.

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

WCF address does not match what I specify in my web.config

In my web.config, I have specified
<services>
<service name="Querier.WCF.Querier"
behaviorConfiguration="QuerierServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="http://myserver:8000/SearcherService"/>
</baseAddresses>
</host>
<endpoint address="net.tcp://myserver:9000/SearcherService"
binding="netTcpBinding"
bindingConfiguration="Binding1"
contract="Querier.WCF.IQuerier" />
</service>
</services>
However, the site is not available at http://myserver:8000/SearcherService,
I for some reason have to go to:
http://myserver/SearcherService/SearcherService.svc
(notice the port is missing)
When I go there, it tells me to run
svcutil.exe http://myserver.mycompanyname.com/SearcherService/SearcherService.svc?wsdl
It added a domain name for some reason and when I try to access the service with WCF storm,
I put in http://mymachine/SearcherService/SearcherService.svc, it discovers all the function names fine, but when I try to run one, I get:
There was no endpoint listening at
net.tcp://myserver:9000/SearcherService
that could accept the message. This is
often caused by an incorrect address
or SOAP action. See InnerException, if
present, for more details.
Any ideas as to why my service URL doesn;t match what I specified in the web.config?
NOTE:
I have set nettcp on the app in IIS and enabled the binding on 9000:*
When you host a WCF service in IIS it is IIS and its configuration who decides the base address for your service and you can only specify relative addresses. The baseaddress only applies to self hosted services.

WCF wsHttpBinding and BasicHttpBinding in same WCF Service Application

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