Single WCF REST service with multiple behaviours - wcf

Is it possible to create a WCF REST 4.0 service which has two endpoints with different behaviours? Specifically I’m looking for one endpoint to use transferMode=Streamed, and the other to use Buffered.
I’ve started off using the WCF REST Service Application, which seems to be a mix of WCF and ASP MVC routing technologies. I can set transferMode for both endpoints in
system.serviceModel/standardEndpoints/webHttpEndpoint/standardEndpoint
but am not having any joy applying additional ones to my routes.
I’m not quite clear where the WCF/MVC separation exists, for example whether the Global.asax counts as one WCF endpoint or whether the routes are individual endpoints, and as a result am not sure how to progress.
Is there a simple Web.config change or attribute I can apply to a service to specify different behaviour?
If not, can I create separate asax files using different behaviours instead of one Global.asax file?
If not, should I create .svc files to map onto my classes as in a normal WCF application?
If not, will I have to create a second project to define different behaviour?

Each service route creates a new ServiceHost. Also, REST Starter Kit is now deprecated, either you should use straight WCF REST 4.0, or you should look into the new WCF Web API stuff at http://wcf.codeplex.com

What about doing it that way:
<services>
<service name="YourNamespace.YourServiceClass">
<endpoint address="stream" kind="webHttpEndpoint" endpointConfiguration="webHttpStreamed" contract="YouServiceContract" />
<endpoint address="buff" kind="webHttpEndpoint" endpointConfiguration="webHttpBuffered" contract="YouServiceContract" />
</service>
</services>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="webHttpStreamed" transferMode="Streamed" />
<standardEndpoint name="webHttpBuffered" transferMode="Buffered" />
</webHttpEndpoint>
</standardEndpoints>
Of course, the two endpoints' addresses must not be overlapping.

Related

WCF Multiple Services - same backing class, different service behavior

I have a single service, one backing binary, that I want to configure to have two different endpoints. The problem is, I want a different serviceBehavior for each endpoint, to specify different security requirements.
E.G:
<service behaviorConfiguration="behavior1" name="MyServiceClass">
<endpoint address="endpoint1" bindingConfiguration="binding1" contract="IMyServiceContract"/>
</service>
<service behaviorConfiguration="behavior2" name="MyServiceClass">
<endpoint address="endpoint2" bindingConfiguration="binding2" contract="IMyServiceContract"/>
</service>
Is such a WCF configuration valid, or attainable in another format?
I'm not sure you can do it from config only, but there exists a code and config solution based around the extensibility point exposed by the IEndpointBehavior interface. This allows you to define behaviors at the endpoint level.
It's not particularly well documented as I don't think it's used very often. According to MSDN:
Endpoint behaviors, which implement IEndpointBehavior, are the primary
mechanism by which you modify the entire service or client run time
for a specific endpoint.
There are two mechanisms for adding endpoint behaviors to a service.
Add the behavior to the Behaviors property.
Implement a custom BehaviorExtensionElement that extends
configuration.
Specific examples of the first option exist here, and here, but I can't find anything about the second.

Service vs Client nodes/sections in Web.Config

What is the difference between the Service node/section and the Client node/section in the configuration section? Why configure endpoints in one section over the other? Which is best for interoperability?
I'm currently building a service that talks to another service. I have endpoints for my clients and endpoints for the other service. Visual Studio seems to lump all the endpoints into the Client section.
I thought that client node was for your consumption and service node was for producing. But when you create a new wcf service visual studio puts your new service endpoint settings under the client node. I have moved my endpoint between both sections trying to figure out what the difference is.
When should I use service over client?
<system.serviceModel>
<services>
<service> <!--I noticed some tutorials and using wcf config edit tool
puts producer endpoint settings here -->
<endpoint blah settings/>
<endpoint blah settings/>
</service>
</services>
<client> <!--Visual Studio puts both producer and consumer endpoint
settings here -->
<endpoint blah settings />
<endpoint blah settings />
<endpoint blah settings />
</client>
<bindings>.....
</system.serviceModel>
Many settings in the WCF web.config (or app.config for that matter) can be shared for both consumers of a service as well as publishers of a service including:
Bindings
Endpoint Behaviors
Diagnostics
However as you have discovered, some config is specific to a service. A well-written service usually specifies:
It's base address. This is a convenience when defining a service as it allows your to define endpoints using relative addresses. Clients however don't use this particular setting as they need an absolute path. For this reason it makes no sense to specify in the section
Services can also be clients. If the client and server endpoints were all plonked together, WCF would not be able to know which should utilise the base address for one thing
Service behavior
By dividing up config between client and server, WCF is better able to know where to look for endpoints.
Which is best for interoperability?
I don't think that has anything to do with it. WCF is a means to achieve interopability but just by using WCF does not imply you will achieve it. Interopability is established when both parties agree on say a particular service contract; canonical data model; data transformation; message version or many of the other patterns as defined by SOA Patterns.org So there are various patterns you must follow. e.g. If you change a method on service contract but have not updated the clients then you have broken interopability by breaking the schema of the service.
Visual Studio seems to lump all the endpoints into the Client section
If your WCF process is both a consumer and producer of WCF services then it should not be putting all the endpoints under

WCF Service, how do I tell if I am publishing WSDL or MEX?

It's my understanding that MEX and WSDL are two different ways of publishing metadata. In the interest of letting clients choose the one they prefer, I'd like to enable both. But I'm not entirely sure how.
My webconfig simply contains:
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
and when browsing to it shows that default page, with a link to serviceblahblah?wsdl which suggests I am publishing just the WSDL.
My question is, is this using MEX, if not how can I also publish MEX, and should I be publishing both?
I'm using the basichttpsbinding if that makes any difference.
and when browsing to it shows that default page, with a link to serviceblahblah?wsdl which suggests I am publishing just the WSDL.
No, you are just visiting the WSDL. What else do you expect to see on that URL? ;-)
The httpGetEnabled attribute enables the publishing of WSDL metadata. As shown in the mexHttpBinding documentation and Getting Started, if you want to expose MEX, you also have to expose a MEX endpoint you can then access:
<!-- the mex endpoint is explosed[sic] at
http://localhost/servicemodelsamples/service.svc/mex -->
<endpoint address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
Clients, when discovering your service, will try to call the /mex endpoint first. If not found, they will request the WSDL. You can see this using Fiddler when you click "Add Service Reference" in Visual Studio and input the plain service URL, and I'm sure this behaviour documented somewhere.

WCF and Multiple Security Models

We're working on a WCF service to house our core API.
We're working on 2 clients to use this API one of which is a WPF desktop app that will most likely authenticate against active directory and reside on the same domain as the API. The other is an ASP.Net web application that will most likely use ASP.Net Membership for security and still reside on the same domain as the WCF service. The plan is for the WCF service to use NetTcp and be hosted inside a Windows Service.
Where possible I would like the WCF service to run as the calling user, I guess this should be fairly straight forward for the desktop app where the user is a domain user. For the web app I guess I will need to create a user for service calls to run under.
Is it possible to get this kind of double approach to security to run over a single WCF service or will I need to make 2 services each with it's own security model?
Also if anyone has any thoughts on best practises/patterns for achieving this that would be great.
Thanks
I've solved the same problem in the following way:
I created two net.tcp binding for every usage.
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="" />
<message clientCredentialType="UserName" />
</security>
</binding>
<binding name="WindowsBinding" >
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Windows" />
</security>
</binding>
Next, I added two endpoints for every services
<service name="SimplePluginService" behaviorConfiguration="CommonBehavior">
<endpoint binding="netTcpBinding" bindingConfiguration="UserNameBinding" name="SimplePluginServiceUserName" contract="ISimplePluginService">
<identity>
<dns value="WCfServer" />
</identity>
</endpoint>
<endpoint binding="netTcpBinding" bindingConfiguration="WindowsBinding" name="SimplePluginServiceWindows" contract="ISimplePluginService">
<identity>
<dns value="WCfServer" />
</identity>
</endpoint>
</service>
Next, I choosed the appropriate endpoint when I create ChannelFactory (ConnectionManager - class, which contains information about user's creditionals).
private readonly Dictionary<Type, Object> channelFactoryDictionary = new Dictionary<Type, Object>();
private ChannelFactory<T> GetChannelFactory<T>() where T : class
{
if (channelFactoryDictionary.Keys.Contains(typeof(T)))
{
return channelFactoryDictionary[typeof(T)] as ChannelFactory<T>;
}
else
{
string endpointName=typeof(T).ToString();
if (ConnectionManager.IsWindowsAuth) endpointName+="Windows";
else endpointName+="UserName";
ChannelFactory<T> channelFactory = new ChannelFactory<T>(endpointName);
if (!ConnectionManager.IsWindowsAuth){
channelFactory.Credentials.UserName.UserName = ConnectionManager.Password;
channelFactory.Credentials.UserName.Password = ConnectionManager.Password;
}
channelFactoryDictionary.Add(typeof(T), channelFactory);
return channelFactory;
}
}
You're conflating a few different issues here. First, I'd claim that your hosting (Windows service) and transport (here given as netTcp) are mostly unrelated to your choice of authentication/authorization, unless you want to rely on ASP.NET membership, in which case you'll want IIS to host your service.
Impersonation is certainly a decent approach to access control on a desktop or in a carefully-curated LDAP environment; I've tended to find, though, that as my services grow their business requirements deviate from policies that are (or can be) represented in Active Directory. Once that happens, your service begins to require more support to keep Windows impersonation working as you'd wish. This often means dealing with WCF extensibility.
Speaking from years of experience, working with WCF security extension points is roughly as painful as a barely-anesthetized root canal. That said, it's quite powerful once the painful work is completed.
I've found that, generally, less pain is better. I can get the security benefits of impersonation by explicitly modeling access restrictions in my code, e.g. using claims-based security and CAS attributes. Taking that approach, a custom IPrincipal-implementing class can obviate the need for impersonation and, with it, much obscure WCF plumbing.
It isn't quite the answer you were looking for, but these are my two cents' worth nevertheless.

WCF to build SOAP based service

I am trying to find some good tutorials that would show me to create a simple SOAP based service using WCF and deploy it. I have been googling for the past 2 hour and can't seem to find any good resource.. Can anyone help me?
As for resources: there's the MSDN WCF Developer Center which has everything from beginner's tutorials to articles and sample code.
Also, check out the screen cast library up on MSDN for some really useful, 10-15 minute chunks of information on just about any topic related to WCF you might be interested in.
Also very good are The Service Station articles in MSDN magazine on various aspects of WCF - some more basic like Serialization in WCF or WCF Bindings in Depth, some more advanced and esoteric - but always worth a look!
Update: for learning WCF and SOAP, check out e.g.
Getting Started Tutorial
First Steps Screencast about WCF (using SOAP!)
and a great many more - there are a ton of tutorial and learnings materials on WCF using SOAP bindings - not just REST stuff for sure!
REST / SOAP endpoints for a WCF service
You can expose the service in two different endpoints. the SOAP one can use the binding that support SOAP e.g. basicHttpBinding, the RESTful one can use the webHttpBinding. I assume your REST service will be in JSON, in that case, you need to configure the two endpoints with the following behaviour configuration
<endpointBehaviors>
<behavior name="jsonBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
An example of endpoint configuration in your scenario is
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="json" binding="webHttpBinding" behaviorConfiguration="jsonBehavior" contract="ITestService"/>
</service>
</services>
so, the service will be available at
http://www.example.com/soap
http://www.example.com/json
Apply [WebGet] to the operation contract to make it RESTful. e.g.
public interface ITestService
{
[OperationContract]
[WebGet]
string HelloWorld(string text)
}
Note, if the REST service is not in JSON, parameters of the operations can not contain complex type.
For plain old XML as return format, this is an example that would work both for SOAP and XML.
[ServiceContract(Namespace = "http://test")]
public interface ITestService
{
[OperationContract]
[WebGet(UriTemplate = "accounts/{id}")]
Account[] GetAccount(string id);
}
POX behavior for REST Plain Old XML
<behavior name="poxBehavior">
<webHttp/>
</behavior>
Endpoints
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="ITestService"/>
</service>
</services>
Service will be available at
http://www.example.com/soap
http://www.example.com/xml
REST request try it in browser,
http://www.example.com/xml/accounts/A123
SOAP request client endpoint configuration for SOAP service after adding the service reference,
<client>
<endpoint address="http://www.example.com/soap" binding="basicHttpBinding"
contract="ITestService" name="BasicHttpBinding_ITestService" />
in C#
TestServiceClient client = new TestServiceClient();
client.GetAccount("A123");
Another way of doing it is to expose two different service contract and each one with specific configuration. This may generate some duplicates at code level, however at the end of the day, you want to make it working.
WCF is a technology for building services. It does not assume that the services are SOAP services or RESTFul or anything else. You have to learn WCf basics such as Service and DataContracts, Endpoints, Bindings etc to be able to work with any kind of service.
The links given marc_s are very helpful for that.
Now as far as SOAP is concerned, it is a format\technology used to transport messages from one endpoint to another. This details is covered by the Binding aspect of the WCF. When you expose and consume services you just have to choose a Binding which uses SOAP.
Hence, you should, using links given by marc_s, learn WCF basics to build a service. Then you will know how to build a service and which binding to choose to use SOAP.
Hope this helps.