J'ai un service WCF et je veux l'exposer en tant que service RESTfull et en tant que service SOAP. Quelqu'un a déjà fait quelque chose comme ça avant?
J'ai un service WCF et je veux l'exposer en tant que service RESTfull et en tant que service SOAP. Quelqu'un a déjà fait quelque chose comme ça avant?
Réponses:
Vous pouvez exposer le service dans deux points de terminaison différents. le SOAP peut utiliser la liaison qui prend en charge SOAP, par exemple basicHttpBinding, le RESTful peut utiliser le webHttpBinding. Je suppose que votre service REST sera en JSON, dans ce cas, vous devez configurer les deux points de terminaison avec la configuration de comportement suivante
<endpointBehaviors>
<behavior name="jsonBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
Un exemple de configuration de point de terminaison dans votre scénario est
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="json" binding="webHttpBinding" behaviorConfiguration="jsonBehavior" contract="ITestService"/>
</service>
</services>
donc, le service sera disponible à
Appliquez [WebGet] au contrat d'exploitation pour le rendre RESTful. par exemple
public interface ITestService
{
[OperationContract]
[WebGet]
string HelloWorld(string text)
}
Notez que si le service REST n'est pas en JSON, les paramètres des opérations ne peuvent pas contenir de type complexe.
Pour le vieux XML pur comme format de retour, ceci est un exemple qui fonctionnerait à la fois pour SOAP et XML.
[ServiceContract(Namespace = "http://test")]
public interface ITestService
{
[OperationContract]
[WebGet(UriTemplate = "accounts/{id}")]
Account[] GetAccount(string id);
}
Comportement POX pour REST Plain Old XML
<behavior name="poxBehavior">
<webHttp/>
</behavior>
Points de terminaison
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="ITestService"/>
</service>
</services>
Le service sera disponible à
Demande REST essayez-le dans le navigateur,
Configuration du point de terminaison client de demande SOAP pour le service SOAP après l'ajout de la référence de service,
<client>
<endpoint address="http://www.example.com/soap" binding="basicHttpBinding"
contract="ITestService" name="BasicHttpBinding_ITestService" />
</client>
en C #
TestServiceClient client = new TestServiceClient();
client.GetAccount("A123");
Une autre façon de le faire est d'exposer deux contrats de service différents et chacun avec une configuration spécifique. Cela peut générer des doublons au niveau du code, mais à la fin de la journée, vous souhaitez le faire fonctionner.
Ce message a déjà une très bonne réponse de "Community wiki" et je recommande également de consulter le blog Web de Rick Strahl, il existe de nombreux bons messages sur WCF Rest comme celui-ci .
J'ai utilisé les deux pour obtenir ce type de service MyService ... Ensuite, je peux utiliser l'interface REST de jQuery ou SOAP de Java.
C'est de mon 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>
Et voici ma classe de service (.svc-codebehind, aucune interface requise):
/// <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;
}
}
En fait, j'utilise uniquement Json ou Xml, mais les deux sont ici à des fins de démonstration. Ce sont des demandes GET pour obtenir des données. Pour insérer des données, j'utiliserais une méthode avec des attributs:
[OperationContract(Name = "MyResourceSave")]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "MyJsonResource")]
public string MyResourceSave(string thing){
//...
Si vous souhaitez uniquement développer un service Web unique et le faire héberger sur de nombreux points de terminaison différents (c.-à-d. SOAP + REST, avec des sorties XML, JSON, CSV, HTML). Vous devriez également envisager d'utiliser ServiceStack que j'ai construit exactement à cette fin, où chaque service que vous développez est automatiquement disponible sur les points de terminaison SOAP et REST prêts à l'emploi sans aucune configuration requise.
L' exemple Hello World montre comment créer un simple avec service avec just (aucune configuration requise):
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 };
}
}
Aucune autre configuration n'est requise, et ce service est immédiatement disponible avec REST dans:
Il est également livré avec une sortie HTML conviviale (lorsqu'il est appelé avec un client HTTP qui a Accept: text / html, par exemple un navigateur) afin que vous puissiez mieux visualiser la sortie de vos services.
La gestion de différents verbes REST est également aussi triviale, voici une application CRUD de service REST complète en 1 page de C # (moins que ce qu'il faudrait pour configurer WCF;):
MSDN semble avoir un article pour cela maintenant:
https://msdn.microsoft.com/en-us/library/bb412196(v=vs.110).aspx
Intro:
Par défaut, Windows Communication Foundation (WCF) rend les points de terminaison disponibles uniquement pour les clients SOAP. Dans Comment: créer un service HTTP Web WCF de base, un point de terminaison est mis à la disposition des clients non SOAP. Il peut arriver que vous souhaitiez rendre le même contrat disponible dans les deux sens, en tant que point de terminaison Web et en tant que point de terminaison SOAP. Cette rubrique montre un exemple de procédure à suivre.
Nous devons définir la configuration du comportement au point de terminaison REST
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" />
</behavior>
</endpointBehaviors>
et aussi à un service
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
Après les comportements, la prochaine étape est les liaisons. Par exemple, basicHttpBinding vers le point de terminaison SOAP et webHttpBinding vers REST .
<bindings>
<basicHttpBinding>
<binding name="soapService" />
</basicHttpBinding>
<webHttpBinding>
<binding name="jsonp" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
Enfin, nous devons définir le point final 2 dans la définition du service. Attention pour l'adresse = "" du noeud final, où le service REST n'est pas nécessaire rien.
<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>
Dans Interface du service, nous définissons l'opération avec ses attributs.
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);
}
}
Rejoindre toutes les parties, ce sera notre définition WCF system.serviceModel.
<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>
Pour tester les deux points de terminaison, nous pouvons utiliser WCFClient pour SOAP et PostMan pour REST .
C'est ce que j'ai fait pour que ça marche. Assurez-vous de mettre
webHttp automaticFormatSelectionEnabled = "true" dans le comportement du point de terminaison.
[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...";
}
}
Modèle de service interne
<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>
Comportement EndPoint
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp automaticFormatSelectionEnabled="true" />
<!-- use JSON serialization -->
</behavior>
</endpointBehaviors>