WCF - same service on different IIS .svc endpoints with multiple interfaces - wcf

I am trying to achieve the following:
Have one 'full' set of services for consumption by internal apps
Expose a subset of these methods to 3rd parties
The way I have tried to go about this is to create one service that implements two interfaces
For example:
Public Service Interface
[ServiceContract(Namespace = "http://www.myurl.com/public/2011/10")]
public partial interface IPublicService
{
[OperationContract]
ResponseObjOne OperationAvailableToEveryone(RequestObjOne request);
}
Private Service Interface
[ServiceContract(Namespace = "http://www.myurl.com/private/2011/10")]
public partial interface IPrivateService
{
[OperationContract]
ResponseObjOne OperationAvailableToEveryone(RequestObjOne request);
[OperationContract]
ResponseObjTwo OperationAvailableInternally(RequestObjTwo request);
}
Service class to implement both interfaces
public class Service : IPrivateService, IPublicService
{
ResponseObjOne OperationAvailableToEveryone(RequestObjOne request)
{ }
ResponseObjTwo OperationAvailableInternally(RequestObjTwo request)
{ }
}
I would now like to be able to configure this to run as two separate endpoints in IIS. So I have an .svc file with the following:
<%# ServiceHost Language="C#" Debug="true" Service="Adactus.Pulse.SOAServices.Service, Adactus.Pulse.SOAServices" %>
And added the following in the web.config:
<service name="Service">
<endpoint address="/public" binding="basicHttpBinding" contract="IPublicService" />
<endpoint address="/private" binding="basicHttpBinding" contract="IPrivateService" />
</service>
But if I browse to the .svc file I now see all operations in the WSDL and if I add /public to the URL I see a 404. So how can I achieve this?
Ideally I would like to add another .svc endpoint and be able to specify the interface as well as the service implementation class in these svc files. Then I can lock down access to the svc in IIS to secure the internal service.
the key is that some of the operations are exposed in both contracts and I don't want to duplicate their implementation.
Any ideas? Am I going about this in the wrong way?
Cheers,
Rob

While it doesn't answer your question, I would definitely not design it this way. I would create a single class library that includes both interfaces and the implementations for them and then I would create separate WCF projects that expose the different interfaces.

Observations: Your Service class to implement both interfaces seems wrong. both interfaces have same method name OperationAvailableToEveryone infact you have to implement your interfaces explicitly.
I even have same query. Infact you cannnot browse with http://localhost:8001/service.svc/public instead http://localhost:8001/public/service.svc. still you can create proxy with http://localhost:8001/service.svc and you use it as normal and your client enpoint address looks like
</client>
<endpoint address="http://localhost:8001/SOAService.svc/public"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IPublicService"
contract="SOAService.IPublicService" name="BasicHttpBinding_IPublicService" />
<endpoint address="http://localhost:8001/SOAService.svc/private"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IPrivateService"
contract="SOAService.IPrivateService" name="BasicHttpBinding_IPrivateService" />
</client>
Hope this helps.

Related

two endpoint within one service host

I have 3 projects in a solution as following:
WCF Service Library "ServiceLib"(contract ICalculator and its implementation Calculator1).
Console Application "ServiceHost" to host WCF Service Library(and another ICalculator implementation Calculator2);
add Calculator1 & Calculator2 into an instance of ServiceHost using method AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "Calculator1"),
AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "Calculator2")
Add Service Reference to "ServiceHost" to my client application(type of Console Application);
an app.config(auto-generated) within this project
question is: How to consume these two Calculators(different logic) from client app side, does it necessary to create two different types of client proxy or other way to do that?
thanks for your hand!
<endpoint address="http://localhost:8000/Calculator" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_ICalculator" contract="Services_BaseAddress.ICalculator"
name="WSHttpBinding_ICalculator">
</endpoint>
<endpoint address="http://localhost:8000/DoubleCalculator" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_ICalculator1" contract="Services_BaseAddress.ICalculator"
name="WSHttpBinding_ICalculator1">
</endpoint>

How can I programmatically create an endpoint and use it in my service instead of obtain it from the web.config?

Basically I want to create this binding that will listen to azure service bus queue:
<services>
<service name="myServiceName">
<endpoint address="sb://****.servicebus.windows.net"
listenUri="sb://****.servicebus.windows.net"
binding="netMessagingBinding"
bindingConfiguration="netMessagingBinding"
behaviorConfiguration="myConfiguration"
name="myServiceEndpoint"
contract="****" />
</service>
I also need to know how I can use it in my service.
Look at your servicehost file (.SVC) it can contain a reference to the factory class that generates your service file. More info here: http://msdn.microsoft.com/en-us/library/aa967286.aspx
By providing your own factory you get an ability to override the generation of your service class via CreateServiceHost method. That will give you more control as to how your service class is created. You can inject your own URL's,l etc.
HTH

WCF service versioning with single SVC

Due to some certain requirement, I've got to use a single svc for multiple service versions. I've separated the interface contract for each version using different namespaces. I have only one class (partial) implementing all the service versions.
My code is as below:
namespace Application.V1
{
[ServiceContract(Namespace = "http://google.com/ApplicationService/v1.0", Name = "IMathService")]
public interface IMathService
}
namespace Application.V2
{
[ServiceContract(Namespace = "http://google.com/ApplicationService/v2.0", Name = "IMathService")]
public interface IMathService
}
The Application/MathServiceV1.cs file:
public partial class MathService : V1.IMathService { }
The Application/MathServiceV2.cs file:
public partial class MathService : V2.IMathService { }
The Application/MathService.cs file:
public partial class MathService {}
I've added the following in the service web.config:
<service behaviorConfiguration="ServiceBehavior" name="Application.MathService">
<endpoint address="V1" binding="wsHttpBinding" contract="Application.V1.IMathService" />
<endpoint address="V2" binding="wsHttpBinding" contract="Application.V2.IMathService" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
I have a file MathService.svc with the following:
<%# ServiceHost Service="Application.MathService, Application"
Factory="Autofac.Integration.Wcf.AutofacServiceHostFactory, Autofac.Integration.Wcf"%>
If I generate a proxy with the address http://localhost:8000/MathService.svc the client endpoints are generated as below:
<client>
<endpoint address="http://localhost:8000/MathService.svc/V1"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMathService"
contract="MathService.IMathService" name="WSHttpBinding_IMathService">
</endpoint>
<endpoint address="http://localhost:8000/MathService.svc/V2"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IMathService1"
contract="MathService.IMathService1" name="WSHttpBinding_IMathService1">
</endpoint>
</client>
My concern is that the client endpoint address is generated with MathService.svc/V1 but I'd like to see V1/MathService.svc.
If i browse the service with the address http://localhost:8000/MathService.svc/V1 i am getting HTTP 400 Bad Request error.
Any suggestions?
Regarding your 400 bad request error - you probably dont have MEX enabled, so making a request without a payload makes no sense to the service.
Here is a question about enabling MEX:
WCF How to enable metadata?
Either enable MEX - or use a proper service consumer to call your service.
Regarding your addressing - you cannot do what you want to do with WCF alone. Because you are using IIS hosted WCF (I assume this because you are using an SVC file), your HTTP request must be directed to the location of your SVC file, and anything after that (/V1 for example) is used to locate the appropriate endpoint. This is just how it works in IIS. Putting the /v1/ BEFORE the file name (MathService.asmx) tells IIS to look for a folder called /v1/ before attempting to locate a file named MathService.asmx - obviously it wont find anything there!
However, you may be able to install a URL rewriter in your Web.config to redirect your preferred URI to the one mentioned above.
Here is some documentation on Url rewriting in asp.net:
http://www.iis.net/learn/extensions/url-rewrite-module/iis-url-rewriting-and-aspnet-routing

Using 2 WCF interfaces in the same svc file

We are trying to communicate with an external WCF service.
The WCF services are exposed via svc files. It appears that there are 2 interfaces exposed via the same svc file.
How can we configure this in the web.config file?
If I understand your question correctly, you have a single class that implements 2 WCF service contracts. In your web.config, you configure an endpoint for each service contract, but under the same <service> node. I've only done this when self-hosting WCF services, not in IIS, but I think if you specify a value for address in your endpoint configuration, it will make it relative to the location of the .svc file:
<service name="YourServiceLibrary.YourServiceClass">
<endpoint address="Service1"
contract="YourServiceLibrary.IService1"
...
/>
<endpoint address="Service2"
contract="YourServiceLibrary.IService2"
...
/>
</service>
You would then setup your client proxies for each service contract to point to http://YourServer/YourServicePath/YourServiceClass.svc/Service1 and http://YourServer/YourServicePath/YourServiceClass.svc/Service2

How to configure WCF service from code when hosted in IIS?

My WCF service exposes an https AND an http endpoint. Apart from the SSL they are identical. They map to the same code.
The ultimate intention is for external users to connect via https, internal users to use http.
In development this gives me a problem. Cassini, the development web server packaged in VS, hates SSL.
I'm wondering if I can configure the service from code, so when running under Cassini, I would not configure https.
Hence the question - How do I configure the service from code if it is IIS hosted? I'd be very happy with alternative answers on how I can persuade Cassini to NOT complain about the https part of the configuration.
"IIS will take care of spinning up the necessary ServiceHost based on your *.svc file - not a whole lot you can do about that, really."
Not too close to the truth. Exactly in the SVC file of your service there is attribute named Factory. Where you can specify the the class and the assebly where the class is located. This class may be your own descendant of Web|DataServiceHostFactory
So your svc markup would look like this
<%# ServiceHost
Language="C#"
Debug="true"
Service="name.space.myService"
CodeBehind="name.space.myService.svc.sc"
Factory = "name.space.WebServiceHostFactoryEx, assembly.name"
%>
The WebServiceHostFactory will be created for every service hit and will recreate your host the way you want it.
You will also need to inherith WebServiceHost and create it the way you need it with certain endpoins, behaviors, addresses, etc settings - whatever you like.
There is very nice post from Michele Bustamante here
EDIT: I figured out the above link is not working anymore, so here it is another one.
I am using this in IIS hosted enviroment for couple of services that are initialized same way.
When you're hosting in IIS, you're leaving a lot of care taking into the realm of IIS - you cannot really grab a hold of your service in this case.
IIS will take care of spinning up the necessary ServiceHost based on your *.svc file - not a whole lot you can do about that, really.
My solution would be different - externalize the <service> tag in your configuration file (web.config):
<system.serviceModel>
<services>
<service configSource="service.dev.config" />
</services>
</system.serviceModel>
In your dev environment, only expose the http endpoint - so your service.dev.config would look something like this:
<service name=".....">
<endpoint name="default"
address="....."
binding="basicHttpBinding" bindingConfiguration="insecure"
contract="......" />
</service>
Create a second service.prod.config which then contains both endpoints - http and https:
<service name=".....">
<endpoint name="default"
address="....."
binding="basicHttpBinding" bindingConfiguration="insecure"
contract="......" />
<endpoint name="secure"
address="....."
binding="basicHttpBinding" bindingConfiguration="secure"
contract="......" />
</service>
and reference that in your web.config on the deployment server.