จุดปลาย REST / SOAP สำหรับบริการ WCF


425

ฉันมีบริการ WCF และฉันต้องการให้เป็นบริการ RESTfull และเป็นบริการ SOAP ใครเคยทำสิ่งนี้มาก่อนบ้าง


คำถามที่ดีและคำตอบที่ดี
จันทรา rv

คำตอบ:


584

คุณสามารถแสดงบริการในสองปลายทางที่แตกต่างกัน SOAP หนึ่งสามารถใช้การเชื่อมที่สนับสนุน SOAP เช่น basicHttpBinding, RESTful หนึ่งสามารถใช้ webHttpBinding ฉันคิดว่าบริการ REST ของคุณจะอยู่ใน JSON ในกรณีนั้นคุณต้องกำหนดค่าจุดปลายสองจุดด้วยการกำหนดค่าลักษณะการทำงานต่อไปนี้

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

ตัวอย่างของการกำหนดค่าจุดปลายในสถานการณ์จำลองของคุณคือ

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

ดังนั้นบริการจะพร้อมใช้งานที่

ใช้ [WebGet] กับสัญญาการดำเนินการเพื่อทำให้ RESTful เช่น

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

หมายเหตุหากเซอร์วิส REST ไม่ได้อยู่ใน JSON พารามิเตอร์ของการดำเนินการต้องไม่มีชนิดที่ซับซ้อน

ตอบกลับโพสต์สำหรับ SOAP และ RESTful POX (XML)

สำหรับ XML เก่าธรรมดาเป็นรูปแบบการส่งคืนนี่เป็นตัวอย่างที่ใช้งานได้ทั้งกับ SOAP และ XML

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

พฤติกรรม POX สำหรับ REST Plain Old XML

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

ปลายทาง

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

บริการจะสามารถใช้ได้ที่

คำขอ REST ลองใช้ในเบราว์เซอร์

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

การ กำหนดค่าจุดสิ้นสุดไคลเอนต์คำขอ SOAPสำหรับบริการ SOAP หลังจากเพิ่มการอ้างอิงบริการ

  <client>
    <endpoint address="http://www.example.com/soap" binding="basicHttpBinding"
      contract="ITestService" name="BasicHttpBinding_ITestService" />
  </client>

ใน C #

TestServiceClient client = new TestServiceClient();
client.GetAccount("A123");

อีกวิธีในการดำเนินการคือการเปิดเผยสัญญาบริการที่แตกต่างกันสองสัญญาและแต่ละรายการมีการกำหนดค่าเฉพาะ สิ่งนี้อาจทำให้เกิดการซ้ำซ้อนในระดับรหัสอย่างไรก็ตามในตอนท้ายของวันคุณต้องการทำให้มันใช้งานได้


11
วิธีการที่ไม่มองเช่นนี้เมื่อผมได้เป็นเจ้าภาพ .svc ใน IIS ในไดเรกทอรีเสมือนบางอย่างเช่นSOMESERVER / myvirtualdir / service.svc ? ฉันจะเข้าถึงได้อย่างไร?
Sunny Milenov

ฉันต้องการดำเนินการหนึ่งขั้นตอนต่อไปและเพิ่มการเชื่อมโยงกับ HTTPS สำหรับที่อยู่ JSON ฉันจะทำอย่างไร stackoverflow.com/questions/18213472/…
Steve

มันบอกว่าสัญญาของฉัน IEvents ไม่ถูกต้องเมื่อฉันพยายามอ้างอิง Service Interface ของฉัน: <service name = "เหตุการณ์"> <endpoint address = "json" binding = "webHttpBinding" behaviorConfiguration = "jsonBehavior" contract = "IEvents" /> IEvents ของฉันมีแอตทริบิวต์ [ServiceContract] บนอินเทอร์เฟซดังนั้นจึงไม่แน่ใจว่าทำไม </service>
PositiveGuy

ฉันจะได้รับlocalhost: 44652 / MyResource / JSONในการทำงาน แต่ฉันไม่สามารถได้รับรหัสการทำงานlocalhost: 44652 / MyResource / 98 / JSON ฉันได้ลองเพิ่ม UriTemplate เป็น "/ {id}" แล้วก็ลอง "events / {id} ด้วย แต่ก็หาไม่เจอเมื่อฉันพยายามที่จะใช้บริการเฉพาะผลงานแรกเท่านั้นไม่แน่ใจว่าจะได้รับหลังได้อย่างไร ในการทำงาน
PositiveGuy

2
จะทำงานกับไฟล์ที่ไม่มีอยู่จริงได้อย่างไร ฉันดูเหมือนจะได้รับข้อผิดพลาด 404 ต้องหายไปบางสิ่งบางอย่าง
RoboJ1M

39

โพสต์นี้มีอยู่แล้วคำตอบที่ดีมากด้วย "วิกิพีเดียชุมชน" และผมก็ขอแนะนำให้ไปดูที่ริกราล์เว็บบล็อกที่มีการโพสต์ดีมากเกี่ยวกับ WCF ส่วนที่เหลือเช่นนี้

ฉันใช้ทั้งสองเพื่อรับ MyService-service ชนิดนี้ ... จากนั้นฉันสามารถใช้ส่วนต่อประสาน REST จาก jQuery หรือ SOAP จาก Java

นี่คือจากเว็บของฉันกำหนดค่า:

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

และนี่คือบริการระดับของฉัน (.svc-codebehind ไม่จำเป็นต้องใช้อินเทอร์เฟซ):

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

จริงๆแล้วฉันใช้แค่ Json หรือ Xml แต่ทั้งคู่อยู่ที่นี่เพื่อการสาธิต สิ่งเหล่านี้คือคำร้องขอ GET เพื่อรับข้อมูล เพื่อแทรกข้อมูลฉันจะใช้วิธีการที่มีคุณสมบัติ:

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

ฉันอยากรู้ว่าคุณจะได้รับประโยชน์อะไรจากการเพิ่มคุณสมบัติ WebGet และ WebInvoke เหล่านี้
Darrel Miller

2
คุณสามารถทำการร้องขอผ่านเบราว์เซอร์: localhost / MyService.svc / MyXmlResource / test และพูดรูปแบบ Json หรือ Xml อย่างชัดเจน หากคุณต้องการวิธีเดียวกันในการตอบสนองทั้งคู่นี่คือลิงค์: blogs.msdn.com/dotnetinterop/archive/2008/11/04/…
Tuomas Hietanen

นี่คือเพื่อการทดสอบ เพียงเพื่อดูว่าปลายทางของคุณทำงานอยู่หรือไม่ คุณดู SoapUI หรือไม่? soapui.org
Darrel Miller

@TuomasHietanen - ฉันไม่ได้รับการตอบสนองประเภท JSON โดยใช้พฤติกรรม webHttp แต่การใช้ enableWebScript ฉันจะได้รับการตอบสนองประเภท JSON ฉันใส่ ResponseFormat เป็น WebMessageFormat.Json ในทางกลับกันฉันไม่สามารถใช้ URItemplate ได้หากฉันใช้ enableWebScript ความคิดใด ๆ
smile.al.d.way

1
@CoffeeAddict - ทำไมคุณควรใช้ inteface เพียงมีอินเทอร์เฟซ คุณจะไม่ใช้อินเทอร์เฟซนี้ซ้ำ มันง่ายกว่านี้
Tuomas Hietanen

25

หากคุณต้องการพัฒนาบริการเว็บเดียวและให้บริการพื้นที่บนปลายทางที่แตกต่างกัน (เช่น SOAP + REST ด้วย XML, JSON, CSV, HTML outputes) คุณควรพิจารณาใช้ServiceStackซึ่งฉันได้สร้างขึ้นเพื่อจุดประสงค์นี้ที่บริการทุกอย่างที่คุณพัฒนานั้นจะมีให้โดยอัตโนมัติทั้งบน SOAP และ REST endpoints แบบไม่ต้องมีการกำหนดค่าใด ๆ

ตัวอย่างHello Worldแสดงวิธีสร้างวิอย่างง่ายพร้อมบริการเพียง (ไม่จำเป็นต้องกำหนดค่า):

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

ไม่ต้องการการกำหนดค่าอื่น ๆ และบริการนี้พร้อมใช้งานทันทีกับ REST ใน:

นอกจากนี้ยังมาพร้อมกับเอาต์พุต HTML ที่เป็นมิตร (เมื่อเรียกด้วยไคลเอนต์ HTTP ที่ยอมรับ: text / htmlเช่นเบราว์เซอร์) เพื่อให้คุณสามารถเห็นภาพผลลัพธ์ของบริการได้ดียิ่งขึ้น

การจัดการคำกริยา REST ที่แตกต่างกันนั้นมีความสำคัญเช่นกันนี่คือแอป RUD บริการที่สมบูรณ์ใน 1 หน้าของ C # (น้อยกว่าที่จะใช้ในการกำหนดค่า WCF;):


7

MSDN ดูเหมือนจะมีบทความในตอนนี้:

https://msdn.microsoft.com/en-us/library/bb412196(v=vs.110).aspx

บทนำ:

ตามค่าเริ่มต้น Windows Communication Foundation (WCF) ทำให้จุดสิ้นสุดพร้อมใช้งานสำหรับไคลเอ็นต์ SOAP เท่านั้น ในวิธีการ: สร้างบริการเว็บ HTTP พื้นฐานของ WCF จุดสิ้นสุดจะพร้อมใช้งานสำหรับไคลเอ็นต์ที่ไม่ใช่ SOAP อาจมีบางครั้งที่คุณต้องการให้สัญญาเดียวกันพร้อมใช้งานทั้งสองวิธีเป็นจุดสิ้นสุดของเว็บและเป็นจุดสิ้นสุดของ SOAP หัวข้อนี้แสดงตัวอย่างของวิธีการทำเช่นนี้


3

เราจะต้องกำหนดค่าพฤติกรรมที่ปลายทางREST

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

หลังจากพฤติกรรมขั้นตอนต่อไปคือการผูก ยกตัวอย่างเช่น basicHttpBinding เพื่อSOAPปลายทางและ webHttpBinding เพื่อREST

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

ในที่สุดเราจะต้องกำหนด 2 จุดสิ้นสุดในข้อกำหนดบริการ ให้ความสนใจกับที่อยู่ = "" ของจุดสิ้นสุดซึ่งไม่จำเป็นต้องใช้บริการ REST

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

ในอินเทอร์เฟซของบริการเรากำหนดการดำเนินการด้วยคุณลักษณะของมัน

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

เข้าร่วมทุกฝ่ายนี่จะเป็นคำจำกัดความของระบบ WCF ของเรา

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

ในการทดสอบทั้งปลายทางเราสามารถใช้WCFClientเพื่อSOAPและPostManเพื่อREST


ทำงานได้ดีตามที่คาดไว้
ชีฟ

0

นี่คือสิ่งที่ฉันทำเพื่อให้มันใช้ได้ ตรวจสอบให้แน่ใจว่าคุณใส่
webHttp automaticFormatSelectionEnabled = "true"ภายในลักษณะการทำงานของอุปกรณ์ปลายทาง

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

รูปแบบการบริการภายใน

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

พฤติกรรมจุดปลาย

  <endpointBehaviors>
    <behavior name="jsonBehavior">
      <webHttp automaticFormatSelectionEnabled="true"  />
      <!-- use JSON serialization -->
    </behavior>
  </endpointBehaviors>
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.