I have one. WCF Service, I want to use it as REST full services and SOAP Service disclosure. Has anyone done such a thing before?
#1 building
MSDN now seems to have an article:
https://msdn.microsoft.com/en-us/library/bb412196(v=vs.110).aspx
Introduction:
By default, Windows Communication Foundation (WCF) makes endpoints available only to SOAP clients. In how to: create a basic WCF Web HTTP service, endpoints are available to non SOAP clients. Sometimes you may want to provide the same contract in the same way, such as a Web endpoint and a SOAP endpoint. This topic shows an example of how to do this.
#2 building
You can expose the service in two different endpoints. SOAP can use bindings that support SOAP, such as basicHttpBinding, and RESTful can use webHttpBinding. I assume that your REST service will use JSON, in which case you need to configure both endpoints with the following behavior configuration
<endpointBehaviors> <behavior name="jsonBehavior"> <enableWebScript/> </behavior> </endpointBehaviors>
An example of endpoint configuration in your scenario is as follows
<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
Apply [WebGet] to the operation contract to make it RESTful. for example
public interface ITestService { [OperationContract] [WebGet] string HelloWorld(string text) }
Note that if the REST service is not in JSON, the parameters of the operation cannot contain complex types.
Reply to SOAP and RESTful POX (XML) posts
For normal old XML as a return format, this is an example for both SOAP and XML.
[ServiceContract(Namespace = "http://test")] public interface ITestService { [OperationContract] [WebGet(UriTemplate = "accounts/{id}")] Account[] GetAccount(string id); }
POX behavior of REST Plain Old XML
<behavior name="poxBehavior"> <webHttp/> </behavior>
Endpoint
<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 in
REST request tried in browser
Add the SOAP request client endpoint configuration of the SOAP service after the service reference,
<client> <endpoint address="http://www.example.com/soap" binding="basicHttpBinding" contract="ITestService" name="BasicHttpBinding_ITestService" /> </client>
In C
TestServiceClient client = new TestServiceClient(); client.GetAccount("A123");
Another approach is to expose two different service contracts, each with a specific configuration. This may generate some duplicates at the code level, but at the end of the day, you want them to work.
#3 building
This post already has a good answer through "community wiki". I also suggest that you read Rick Strahl's Weblog. It's about how good a position WCF has to rest in such .
I use both to get this MyService service... Then I can use jQuery's REST interface or Java's SOAP.
This is from my Web.Config:
<system.serviceModel> <services> <service name="MyService" behaviorConfiguration="MyServiceBehavior"> <endpoint name="rest" address="" binding="webHttpBinding" contract="MyService" behaviorConfiguration="restBehavior"/> <endpoint name="mex" address="mex" binding="mexHttpBinding" contract="MyService"/> <endpoint name="soap" address="soap" binding="basicHttpBinding" contract="MyService"/> </service> </services> <behaviors> <serviceBehaviors> <behavior name="MyServiceBehavior"> <serviceMetadata httpGetEnabled="true"/> <serviceDebug includeExceptionDetailInFaults="true" /> </behavior> </serviceBehaviors> <endpointBehaviors> <behavior name="restBehavior"> <webHttp/> </behavior> </endpointBehaviors> </behaviors> </system.serviceModel>
This is my service class (. SVC codebehind, no interface required):
/// <summary> MyService documentation here ;) </summary> [ServiceContract(Name = "MyService", Namespace = "http://myservice/", SessionMode = SessionMode.NotAllowed)] //[ServiceKnownType(typeof (IList<MyDataContractTypes>))] [ServiceBehavior(Name = "MyService", Namespace = "http://myservice/")] public class MyService { [OperationContract(Name = "MyResource1")] [WebGet(ResponseFormat = WebMessageFormat.Xml, UriTemplate = "MyXmlResource/{key}")] public string MyResource1(string key) { return "Test: " + key; } [OperationContract(Name = "MyResource2")] [WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "MyJsonResource/{key}")] public string MyResource2(string key) { return "Test: " + key; } }
In fact, I only use Json or Xml, but these are for demonstration purposes. These are GET requests to GET data. To insert data, I use methods with attributes:
[OperationContract(Name = "MyResourceSave")] [WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "MyJsonResource")] public string MyResourceSave(string thing){ //...
#4 building
If you only want to develop a single Web service and host it on many different endpoints (that is, SOAP + REST, using XML, JSON, CSV, HTML output). You should also consider using the ServiceStack , each service you develop can be used automatically on SOAP and REST endpoints out of the box without any configuration.
Hello World The example demonstrates how to use just to create a simple service (no configuration required):
public class Hello { public string Name { get; set; } } public class HelloResponse { public string Result { get; set; } } public class HelloService : IService { public object Any(Hello request) { return new HelloResponse { Result = "Hello, " + request.Name }; } }
Without additional configuration, this service can be used in REST immediately:
It is also built in. Friendly HTML output (when using an HTTP client call with Accept: text / html, such as a browser), so you can better visualize the output of the service.
It's also easy to handle different REST verbs. Here is a complete REST Service CRUD application, in page C (less than what is needed to configure WCF);
#5 building
We must define the behavior configuration to the REST endpoint
<endpointBehaviors> <behavior name="restfulBehavior"> <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" /> </behavior> </endpointBehaviors>
There's another service
<serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors>
After the behavior, the next step is binding. For example, basicHttpBinding to the SOAP endpoint, and webHttpBinding to REST.
<bindings> <basicHttpBinding> <binding name="soapService" /> </basicHttpBinding> <webHttpBinding> <binding name="jsonp" crossDomainScriptAccessEnabled="true" /> </webHttpBinding> </bindings>
Finally, we must define the 2 endpoint in the service definition. "Note the address of the endpoint =" ", where the REST service is unnecessary.".
<services> <service name="ComposerWcf.ComposerService"> <endpoint address="" behaviorConfiguration="restfulBehavior" binding="webHttpBinding" bindingConfiguration="jsonp" name="jsonService" contract="ComposerWcf.Interface.IComposerService" /> <endpoint address="soap" binding="basicHttpBinding" name="soapService" contract="ComposerWcf.Interface.IComposerService" /> <endpoint address="mex" binding="mexHttpBinding" name="metadata" contract="IMetadataExchange" /> </service> </services>
In the interface of a service, we use its properties to define operations.
namespace ComposerWcf.Interface { [ServiceContract] public interface IComposerService { [OperationContract] [WebInvoke(Method = "GET", UriTemplate = "/autenticationInfo/{app_id}/{access_token}", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)] Task<UserCacheComplexType_RootObject> autenticationInfo(string app_id, string access_token); } }
Join all parties, this will be our WCF system.serviceModel definition.
<system.serviceModel> <behaviors> <endpointBehaviors> <behavior name="restfulBehavior"> <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" /> </behavior> </endpointBehaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" /> <serviceDebug includeExceptionDetailInFaults="false" /> </behavior> </serviceBehaviors> </behaviors> <bindings> <basicHttpBinding> <binding name="soapService" /> </basicHttpBinding> <webHttpBinding> <binding name="jsonp" crossDomainScriptAccessEnabled="true" /> </webHttpBinding> </bindings> <protocolMapping> <add binding="basicHttpsBinding" scheme="https" /> </protocolMapping> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> <services> <service name="ComposerWcf.ComposerService"> <endpoint address="" behaviorConfiguration="restfulBehavior" binding="webHttpBinding" bindingConfiguration="jsonp" name="jsonService" contract="ComposerWcf.Interface.IComposerService" /> <endpoint address="soap" binding="basicHttpBinding" name="soapService" contract="ComposerWcf.Interface.IComposerService" /> <endpoint address="mex" binding="mexHttpBinding" name="metadata" contract="IMetadataExchange" /> </service> </services> </system.serviceModel>
To test both endpoints, we can use WCFClient to SOAP and PostMan to REST.
#6 building
That's what I do. Make sure you put it.
webHttp automaticFormatSelectionEnabled = "true" internal endpoint behavior.
[ServiceContract] public interface ITestService { [WebGet(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "/product", ResponseFormat = WebMessageFormat.Json)] string GetData(); } public class TestService : ITestService { public string GetJsonData() { return "I am good..."; } }
Internal service mode
<service name="TechCity.Business.TestService"> <endpoint address="soap" binding="basicHttpBinding" name="SoapTest" bindingName="BasicSoap" contract="TechCity.Interfaces.ITestService" /> <endpoint address="mex" contract="IMetadataExchange" binding="mexHttpBinding"/> <endpoint behaviorConfiguration="jsonBehavior" binding="webHttpBinding" name="Http" contract="TechCity.Interfaces.ITestService" /> <host> <baseAddresses> <add baseAddress="http://localhost:8739/test" /> </baseAddresses> </host> </service>
End-point behavior
<endpointBehaviors> <behavior name="jsonBehavior"> <webHttp automaticFormatSelectionEnabled="true" /> <!-- use JSON serialization --> </behavior> </endpointBehaviors>