У мене є служба WCF, і я хочу розкрити її як послугу RESTfull і як послугу SOAP. Хтось робив щось подібне раніше?
У мене є служба WCF, і я хочу розкрити її як послугу RESTfull і як послугу SOAP. Хтось робив щось подібне раніше?
Відповіді:
Ви можете виставити послугу у двох різних кінцевих точках. 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, параметри операцій не можуть містити складний тип.
Для простого старого 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-запит спробуйте в браузері,
Конфігурація кінцевої точки запиту клієнта для сервісу 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");
Інший спосіб зробити це - розкрити два різні договори на обслуговування, і кожен з конкретною конфігурацією. Це може генерувати деякі дублікати на рівні коду, проте в кінці дня ви хочете, щоб він працював.
Цей пост вже має дуже гарну відповідь "Вікі спільноти", і я також рекомендую переглянути веб-блог Ріка Страля, є багато хороших дописів про WCF відпочинок, як це .
Я використовував обидва для отримання такого роду MyService-сервісу ... Тоді я можу використовувати інтерфейс REST від jQuery або SOAP від Java.
Це з мого 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>
І це мій сервісний клас (.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){
//...
Якщо ви хочете розробити єдиний веб-сервіс і розмістити його на багатьох різних кінцевих точках (наприклад, SOAP + REST, з виводами XML, JSON, CSV, HTML). Вам слід також розглянути можливість використання ServiceStack, який я створив саме для цієї мети, коли кожна розроблена вами послуга автоматично доступна як у кінцевих точках SOAP, так і в REST, поза коробкою без необхідності будь-якої конфігурації.
Приклад 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-клієнтом, який має Accept: текст / html, наприклад, браузер), щоб ви могли краще візуалізувати результати своїх служб.
Поводження з різними дієсловами REST також тривіальне, ось повний додаток CRUD-служби CRUD на 1 сторінці C # (менше, ніж потрібно для налаштування WCF;):
Здається, у MSDN зараз є стаття для цього:
https://msdn.microsoft.com/en-us/library/bb412196(v=vs.110).aspx
Вступ:
За замовчуванням Windows Communication Foundation (WCF) робить кінцеві точки доступними лише для клієнтів SOAP. Як зробити: Створення базової веб-сервісу HTTP WCF, кінцева точка стає доступною для клієнтів, які не входять в SOAP. Можуть бути випадки, коли ви хочете зробити один і той же договір доступним обома способами, як кінцева точка веб-сторінки та кінцева точка SOAP. У цій темі показаний приклад того, як це зробити.
Ми повинні визначити конфігурацію поведінки до кінцевої точки 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 визначення.
<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 .
Це те, що я зробив, щоб він працював. Переконайтеся, що ви поклали
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>
Поведінка EndPoint
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp automaticFormatSelectionEnabled="true" />
<!-- use JSON serialization -->
</behavior>
</endpointBehaviors>