Tôi có một dịch vụ WCF và tôi muốn trưng bày nó vừa là dịch vụ RESTfull vừa là dịch vụ SOAP. Bất cứ ai đã làm một cái gì đó như thế này trước đây?
Tôi có một dịch vụ WCF và tôi muốn trưng bày nó vừa là dịch vụ RESTfull vừa là dịch vụ SOAP. Bất cứ ai đã làm một cái gì đó như thế này trước đây?
Câu trả lời:
Bạn có thể trưng ra dịch vụ ở hai điểm cuối khác nhau. người SOAP có thể sử dụng liên kết hỗ trợ SOAP, ví dụ basicHttpBinding, RESTful có thể sử dụng webHttpBinding. Tôi giả sử dịch vụ REST của bạn sẽ ở dạng JSON, trong trường hợp đó, bạn cần định cấu hình hai điểm cuối với cấu hình hành vi sau
<endpointBehaviors>
<behavior name="jsonBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
Một ví dụ về cấu hình điểm cuối trong kịch bản của bạn là
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="json" binding="webHttpBinding" behaviorConfiguration="jsonBehavior" contract="ITestService"/>
</service>
</services>
vì vậy, dịch vụ sẽ có sẵn tại
Áp dụng [WebGet] cho hợp đồng vận hành để biến nó thành RESTful. ví dụ
public interface ITestService
{
[OperationContract]
[WebGet]
string HelloWorld(string text)
}
Lưu ý, nếu dịch vụ REST không có trong JSON, các tham số của các hoạt động không thể chứa loại phức tạp.
Đối với XML cũ đơn giản là định dạng trả về, đây là một ví dụ sẽ hoạt động cho cả SOAP và XML.
[ServiceContract(Namespace = "http://test")]
public interface ITestService
{
[OperationContract]
[WebGet(UriTemplate = "accounts/{id}")]
Account[] GetAccount(string id);
}
Hành vi POX cho REST Plain XML cũ
<behavior name="poxBehavior">
<webHttp/>
</behavior>
Điểm cuối
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="ITestService"/>
</service>
</services>
Dịch vụ sẽ có sẵn tại
Yêu cầu REST thử nó trong trình duyệt,
SOAP yêu cầu cấu hình điểm cuối của máy khách cho dịch vụ SOAP sau khi thêm tham chiếu dịch vụ,
<client>
<endpoint address="http://www.example.com/soap" binding="basicHttpBinding"
contract="ITestService" name="BasicHttpBinding_ITestService" />
</client>
trong C #
TestServiceClient client = new TestServiceClient();
client.GetAccount("A123");
Một cách khác để làm điều đó là để lộ hai hợp đồng dịch vụ khác nhau và mỗi hợp đồng có cấu hình cụ thể. Điều này có thể tạo ra một số trùng lặp ở cấp mã, tuy nhiên vào cuối ngày, bạn muốn làm cho nó hoạt động.
Bài đăng này đã có một câu trả lời rất hay của "Cộng đồng wiki" và tôi cũng khuyên bạn nên xem Blog Web của Rick Strahl, có nhiều bài viết hay về WCF Rest như thế này .
Tôi đã sử dụng cả hai để có được loại dịch vụ MyService này ... Sau đó tôi có thể sử dụng giao diện REST từ jQuery hoặc SOAP từ Java.
Đây là từ Web.Config của tôi:
<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>
Và đây là lớp dịch vụ của tôi (.svc-codebehind, không yêu cầu giao diện):
/// <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;
}
}
Trên thực tế tôi chỉ sử dụng Json hoặc Xml nhưng cả hai đều ở đây cho mục đích demo. Đó là những yêu cầu GET để lấy dữ liệu. Để chèn dữ liệu tôi sẽ sử dụng phương thức với các thuộc tính:
[OperationContract(Name = "MyResourceSave")]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "MyJsonResource")]
public string MyResourceSave(string thing){
//...
Nếu bạn chỉ muốn phát triển một dịch vụ web duy nhất và được lưu trữ trên nhiều điểm cuối khác nhau (ví dụ SOAP + REST, với các kết quả XML, JSON, CSV, HTML). Bạn cũng nên cân nhắc sử dụng ServiceStack mà tôi đã xây dựng cho chính xác mục đích này, nơi mọi dịch vụ bạn phát triển đều tự động có sẵn trên cả hai điểm cuối SOAP và REST mà không cần bất kỳ cấu hình nào.
Các Hello World ví dụ cho thấy cách để tạo ra một đơn giản với dịch vụ chỉ với (không cần config):
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 };
}
}
Không cần cấu hình nào khác và dịch vụ này ngay lập tức có sẵn với REST trong:
Nó cũng được tích hợp sẵn với đầu ra HTML thân thiện (khi được gọi với ứng dụng khách HTTP có Chấp nhận: text / html, ví dụ như trình duyệt) để bạn có thể hình dung rõ hơn về đầu ra của dịch vụ.
Xử lý các động từ REST khác nhau cũng không đáng kể, đây là một ứng dụng CRUD dịch vụ REST hoàn chỉnh trong 1 trang của C # (ít hơn mức cần thiết để định cấu hình WCF;):
MSDN dường như có một bài viết cho điều này ngay bây giờ:
https://msdn.microsoft.com/en-us/l Library / bb412196 (v = vs.110) .aspx
Giới thiệu:
Theo mặc định, Windows Communication Foundation (WCF) chỉ cung cấp các điểm cuối cho các máy khách SOAP. Trong Cách thực hiện: Tạo Dịch vụ HTTP Web WCF cơ bản, điểm cuối được cung cấp cho các máy khách không SOAP. Có thể đôi khi bạn muốn cung cấp cùng một hợp đồng theo cả hai cách, như một điểm cuối Web và như một điểm cuối SOAP. Chủ đề này cho thấy một ví dụ về cách làm điều này.
Chúng ta phải xác định cấu hình hành vi cho điểm cuối REST
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" />
</behavior>
</endpointBehaviors>
và cũng cho một dịch vụ
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
Sau các hành vi, bước tiếp theo là các ràng buộc. Ví dụ: basicHttpBinding to SOAP endpoint và webHttpBinding to REST .
<bindings>
<basicHttpBinding>
<binding name="soapService" />
</basicHttpBinding>
<webHttpBinding>
<binding name="jsonp" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
Cuối cùng, chúng ta phải xác định 2 điểm cuối trong định nghĩa dịch vụ. Chú ý đến địa chỉ = "" của điểm cuối, nơi dịch vụ REST không cần thiết.
<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>
Trong Giao diện của dịch vụ, chúng tôi xác định hoạt động với các thuộc tính của nó.
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);
}
}
Tham gia tất cả các bên, đây sẽ là định nghĩa WCF system.serviceModel của chúng tôi.
<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>
Để kiểm tra cả hai điểm cuối, chúng ta có thể sử dụng WCFClient để SOAP và PostMan để REST .
Đây là những gì tôi đã làm để làm cho nó hoạt động. Hãy chắc chắn rằng bạn đặt
webHttp AutomaticFormatSelectionEnables = "true" bên trong hành vi điểm cuối.
[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...";
}
}
Mô hình dịch vụ bên trong
<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>
Hành vi Endpoint
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp automaticFormatSelectionEnabled="true" />
<!-- use JSON serialization -->
</behavior>
</endpointBehaviors>