Saya memiliki layanan WCF dan saya ingin mengeksposnya sebagai layanan RESTfull dan sebagai layanan SOAP. Adakah yang pernah melakukan hal seperti ini sebelumnya?
Saya memiliki layanan WCF dan saya ingin mengeksposnya sebagai layanan RESTfull dan sebagai layanan SOAP. Adakah yang pernah melakukan hal seperti ini sebelumnya?
Jawaban:
Anda dapat mengekspos layanan dalam dua titik akhir yang berbeda. satu SOAP dapat menggunakan pengikatan yang mendukung SOAP misalnya basicHttpBinding, yang SISA dapat menggunakan webHttpBinding. Saya berasumsi layanan REST Anda akan berada di JSON, dalam hal ini, Anda perlu mengonfigurasi dua titik akhir dengan konfigurasi perilaku berikut
<endpointBehaviors>
<behavior name="jsonBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
Contoh konfigurasi titik akhir dalam skenario Anda adalah
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="json" binding="webHttpBinding" behaviorConfiguration="jsonBehavior" contract="ITestService"/>
</service>
</services>
jadi, layanan akan tersedia di
Terapkan [WebGet] ke kontrak operasi untuk membuatnya TENANG. misalnya
public interface ITestService
{
[OperationContract]
[WebGet]
string HelloWorld(string text)
}
Catatan, jika layanan REST tidak dalam JSON, parameter operasi tidak dapat berisi tipe kompleks.
Untuk XML tua biasa sebagai format pengembalian, ini adalah contoh yang akan bekerja untuk SOAP dan XML.
[ServiceContract(Namespace = "http://test")]
public interface ITestService
{
[OperationContract]
[WebGet(UriTemplate = "accounts/{id}")]
Account[] GetAccount(string id);
}
Perilaku POX untuk REST Plain Old XML
<behavior name="poxBehavior">
<webHttp/>
</behavior>
Titik akhir
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="ITestService"/>
</service>
</services>
Layanan akan tersedia di
Permintaan REST mencobanya di browser,
SOAP meminta konfigurasi titik akhir klien untuk layanan SOAP setelah menambahkan referensi layanan,
<client>
<endpoint address="http://www.example.com/soap" binding="basicHttpBinding"
contract="ITestService" name="BasicHttpBinding_ITestService" />
</client>
dalam C #
TestServiceClient client = new TestServiceClient();
client.GetAccount("A123");
Cara lain untuk melakukannya adalah mengekspos dua kontrak layanan yang berbeda dan masing-masing dengan konfigurasi spesifik. Ini dapat menghasilkan beberapa duplikat di tingkat kode, namun pada akhirnya, Anda ingin membuatnya berfungsi.
Posting ini sudah memiliki jawaban yang sangat bagus oleh "Komunitas wiki" dan saya juga merekomendasikan untuk melihat Blog Web Rick Strahl, ada banyak posting bagus tentang WCF Istirahat seperti ini .
Saya menggunakan keduanya untuk mendapatkan layanan MyService semacam ini ... Kemudian saya bisa menggunakan antarmuka-REST dari jQuery atau SOAP dari Java.
Ini dari Web saya. Konfigurasi:
<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>
Dan ini adalah kelas layanan saya (.svc-codebehind, tidak diperlukan antarmuka):
/// <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;
}
}
Sebenarnya saya hanya menggunakan Json atau Xml tetapi keduanya ada di sini untuk tujuan demo. Itu adalah GET-permintaan untuk mendapatkan data. Untuk memasukkan data, saya akan menggunakan metode dengan atribut:
[OperationContract(Name = "MyResourceSave")]
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, UriTemplate = "MyJsonResource")]
public string MyResourceSave(string thing){
//...
Jika Anda hanya ingin mengembangkan satu layanan web dan memilikinya di-host pada banyak titik akhir yang berbeda (yaitu SOAP + REST, dengan XML, JSON, CSV, output HTML). Anda juga harus mempertimbangkan menggunakan ServiceStack yang telah saya buat untuk tujuan persis ini di mana setiap layanan yang Anda kembangkan tersedia secara otomatis pada SOAP dan REST endpoint out-of-the-box tanpa konfigurasi apa pun yang diperlukan.
Contoh Hello World menunjukkan cara membuat layanan sederhana dengan adil (tidak perlu konfigurasi):
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 };
}
}
Tidak diperlukan konfigurasi lain, dan layanan ini segera tersedia dengan REST di:
Itu juga datang built-in dengan output HTML yang bersahabat (ketika dipanggil dengan klien HTTP yang memiliki Terima: teks / html misalnya browser) sehingga Anda dapat memvisualisasikan output layanan Anda dengan lebih baik.
Menangani berbagai kata kerja REST juga sepele, berikut adalah aplikasi CRUD layanan-REST lengkap dalam 1 halaman C # (kurang dari yang dibutuhkan untuk mengonfigurasi WCF;):
MSDN tampaknya memiliki artikel untuk ini sekarang:
https://msdn.microsoft.com/en-us/library/bb412196(v=vs.110).aspx
Pengantar:
Secara default, Windows Communication Foundation (WCF) membuat titik akhir hanya tersedia untuk klien SOAP. Dalam Cara: Membuat Layanan HTTP Web WCF Dasar, titik akhir dibuat tersedia untuk klien non-SOAP. Mungkin ada saat-saat ketika Anda ingin membuat kontrak yang sama tersedia dua arah, sebagai titik akhir Web dan sebagai titik akhir SOAP. Topik ini menunjukkan contoh cara melakukan ini.
Kita harus mendefinisikan konfigurasi perilaku ke titik akhir REST
<endpointBehaviors>
<behavior name="restfulBehavior">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped" automaticFormatSelectionEnabled="False" />
</behavior>
</endpointBehaviors>
dan juga ke layanan
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
Setelah perilaku, langkah selanjutnya adalah binding. Misalnya basicHttpBinding ke SOAP endpoint dan webHttpBinding ke REST .
<bindings>
<basicHttpBinding>
<binding name="soapService" />
</basicHttpBinding>
<webHttpBinding>
<binding name="jsonp" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
Akhirnya kita harus mendefinisikan 2 titik akhir dalam definisi layanan. Perhatian untuk alamat = "" titik akhir, di mana untuk layanan REST tidak diperlukan apa-apa.
<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>
Dalam Antarmuka layanan, kami mendefinisikan operasi dengan atributnya.
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);
}
}
Bergabung dengan semua pihak, ini akan menjadi definisi system.serviceModel WCF kami.
<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>
Untuk menguji kedua titik akhir, kita dapat menggunakan WCFClient untuk SOAP dan PostMan untuk REST .
Inilah yang saya lakukan untuk membuatnya bekerja. Pastikan Anda memasukkan
webHttp automaticFormatSelectionEnabled = "true" di dalam perilaku endpoint.
[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...";
}
}
Model layanan di dalam
<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>
Perilaku EndPoint
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp automaticFormatSelectionEnabled="true" />
<!-- use JSON serialization -->
</behavior>
</endpointBehaviors>