webentwicklung-frage-antwort-db.com.de

REST / SOAP Endpunkte für einen WCF-Dienst

Ich habe einen WCF-Dienst und möchte ihn sowohl als RESTful-Dienst als auch als SOAP -Dienst bereitstellen. Jemand hat so etwas schon einmal gemacht?

413
Wessam Zeidan

Sie können den Dienst an zwei verschiedenen Endpunkten verfügbar machen Die SOAP Eins kann die Bindung verwenden, die support SOAP z. basicHttpBinding kann der RESTful die webHttpBinding verwenden. Ich gehe davon aus, dass Ihr REST -Dienst in JSON ausgeführt wird. In diesem Fall müssen Sie die beiden Endpunkte mit der folgenden Verhaltenskonfiguration konfigurieren

<endpointBehaviors>
  <behavior name="jsonBehavior">
    <enableWebScript/>
  </behavior>
</endpointBehaviors>

Ein Beispiel für die Endpunktkonfiguration in Ihrem Szenario ist 

<services>
  <service name="TestService">
    <endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
    <endpoint address="json" binding="webHttpBinding"  behaviorConfiguration="jsonBehavior" contract="ITestService"/>
  </service>
</services>

der Dienst wird also unter verfügbar sein

Wenden Sie [WebGet] auf den Operationsvertrag an, um ihn RESTful zu machen.

public interface ITestService
{
   [OperationContract]
   [WebGet]
   string HelloWorld(string text)
}

Wenn sich der Dienst REST nicht in JSON befindet, können die Parameter der Operationen keinen komplexen Typ enthalten.

Antworten Sie auf den Beitrag für SOAP und RESTful POX (XML)

Für einfaches altes XML als Rückgabeformat ist dies ein Beispiel, das sowohl für SOAP als auch für XML funktionieren würde.

[ServiceContract(Namespace = "http://test")]
public interface ITestService
{
    [OperationContract]
    [WebGet(UriTemplate = "accounts/{id}")]
    Account[] GetAccount(string id);
}

POX-Verhalten für REST Plain Old XML

<behavior name="poxBehavior">
  <webHttp/>
</behavior>

Endpunkte

<services>
  <service name="TestService">
    <endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
    <endpoint address="xml" binding="webHttpBinding"  behaviorConfiguration="poxBehavior" contract="ITestService"/>
  </service>
</services>

Service wird verfügbar sein bei

REST request Versuchen Sie es im Browser,

http://www.example.com/xml/accounts/A123

SOAP Anforderung Clientendpunktkonfiguration für SOAP Dienst nach Hinzufügen der Dienstreferenz.

  <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");

Eine andere Möglichkeit besteht darin, zwei unterschiedliche Serviceverträge und jeweils einen spezifischen Konfigurationsvertrag zu veröffentlichen. Dies kann zu Duplikaten auf Codeebene führen. Am Ende des Tages möchten Sie jedoch, dass es funktioniert.

575
Ray Lu

Dieser Beitrag hat bereits eine sehr gute Antwort von "Community Wiki" und ich empfehle auch einen Blick auf Rick Strahls Web-Blog. Es gibt viele gute Beiträge zu WCF Rest wie this .

Ich habe beide benutzt, um diese Art von MyService-Service zu erhalten ... Dann kann ich die REST-Schnittstelle von jQuery oder SOAP von Java verwenden.

Dies ist aus meiner 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>

Und das ist meine Serviceklasse (.svc-codebehind, keine Schnittstellen erforderlich):

    /// <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;
    }
}

Eigentlich verwende ich nur Json oder Xml, aber beide sind hier zu Demonstrationszwecken. Das sind GET-Requests zum Abrufen von Daten. Um Daten einzufügen, würde ich eine Methode mit Attributen verwenden:

[OperationContract(Name = "MyResourceSave")]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "MyJsonResource")]
public string MyResourceSave(string thing){
    //...
36
Tuomas Hietanen

Wenn Sie nur einen einzelnen Web-Service entwickeln und auf vielen verschiedenen Endpunkten hosten möchten (d. H. SOAP + REST mit XML-, JSON-, CSV- und HTML-Ausgaben). Sie sollten auch die Verwendung von ServiceStack in Betracht ziehen, das ich genau für diesen Zweck erstellt habe, wobei jeder von Ihnen entwickelte Dienst automatisch auf den Endpunkten SOAP und REST verfügbar ist. the-box ohne Konfiguration.

Das Hello World Beispiel zeigt, wie Sie einen einfachen with-Dienst mit nur (keine Konfiguration) erstellen können:

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 };
    }
}

Es ist keine weitere Konfiguration erforderlich. Dieser Dienst ist ab sofort verfügbar mit REST in:

Es ist auch mit einer freundlichen HTML-Ausgabe (bei Aufruf mit einem HTTP-Client mit Accept: text/html z. B. einem Browser) eingebaut, sodass Sie die Ausgabe Ihrer Services besser visualisieren können .

Die Verarbeitung verschiedener REST - Verben ist ebenfalls trivial. Hier ist eine vollständige REST-Service-CRUD-App auf 1 Seite von C # (weniger als WCF zu konfigurieren;):

24
mythz

MSDN scheint dafür jetzt einen Artikel zu haben: 

https://msdn.Microsoft.com/de-de/library/bb412196(v=vs.110).aspx

Intro: 

Standardmäßig stellt Windows Communication Foundation (WCF) Endpunkte nur für SOAP -Clients zur Verfügung. In Gewusst wie: Erstellen eines einfachen WCF-Web-HTTP-Service wird ein Endpunkt für Nicht-SOAP-Clients verfügbar gemacht. Es kann vorkommen, dass Sie denselben Vertrag auf beide Arten als Web-Endpunkt und als SOAP -Endpunkt verfügbar machen möchten. Dieses Thema zeigt ein Beispiel dafür.

6
FMFF

Wir müssen die Verhaltenskonfiguration aufRESTEndpunkt definieren

<endpointBehaviors>
  <behavior name="restfulBehavior">
   <webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" />
  </behavior>
</endpointBehaviors>

und auch zu einem Dienst 

<serviceBehaviors>
   <behavior>
     <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
      <serviceDebug includeExceptionDetailInFaults="false" />
   </behavior>
</serviceBehaviors>

Nach dem Verhalten sind die Bindungen der nächste Schritt. Zum Beispiel basicHttpBinding anSOAPEndpunkt und webHttpBinding anREST.

<bindings>
   <basicHttpBinding>
     <binding name="soapService" />
   </basicHttpBinding>
   <webHttpBinding>
     <binding name="jsonp" crossDomainScriptAccessEnabled="true" />
   </webHttpBinding>
</bindings>

Schließlich müssen wir den Endpunkt 2 in der Service-Definition definieren. Achtung für die Adresse = "" des Endpunktes, wobei zum REST -Dienst nichts notwendig ist.

<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 der Schnittstelle des Dienstes definieren wir die Operation mit ihren Attributen. 

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);
    }
}

Bei allen Teilnehmern wird dies unsere WCF-System.serviceModel-Definition sein.

<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>

Um beide Endpunkte zu testen, können wir WCFClient toSOAPund PostMan toRESTverwenden.

2
Jailson Evora

Das habe ich getan, damit es funktioniert. Stellen Sie sicher, dass Sie setzen
webHttp automaticFormatSelectionEnabled = "true" innerhalb des Endpunktverhaltens.

[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...";
    }
}

Im Servicemodell

   <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>

EndPoint-Verhalten

  <endpointBehaviors>
    <behavior name="jsonBehavior">
      <webHttp automaticFormatSelectionEnabled="true"  />
      <!-- use JSON serialization -->
    </behavior>
  </endpointBehaviors>
0