У меня есть служба 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>
Endpoints
<services>
<service name="TestService">
<endpoint address="soap" binding="basicHttpBinding" contract="ITestService"/>
<endpoint address="xml" binding="webHttpBinding" behaviorConfiguration="poxBehavior" contract="ITestService"/>
</service>
</services>
Сервис будет доступен на
Запрос REST попробуйте в браузере,
Конфигурация конечной точки клиента 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");
Еще один способ сделать это - выставить два разных сервисных контракта и каждый с определенной конфигурацией. Это может создать некоторые дубликаты на уровне кода, однако в конце дня вы хотите, чтобы он работал.
На этот пост уже получен очень хороший ответ от "Сообщества вики", и я также рекомендую взглянуть на веб-блог Рика Страла, там много хороших постов о WCF Rest, как это .
Я использовал оба, чтобы получить этот вид 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: text / html, например, браузер), чтобы вы могли лучше визуализировать выходные данные своих служб.
Обработка различных глаголов REST также тривиальна, вот полное CRUD-приложение REST-service на 1 странице C # (меньше, чем требуется для настройки WCF;):
У MSDN сейчас есть статья для этого:
https://msdn.microsoft.com/en-us/library/bb412196(v=vs.110).aspx
Вступление:
По умолчанию Windows Communication Foundation (WCF) делает конечные точки доступными только для клиентов SOAP. В разделе Практическое руководство. Создание базовой веб-службы WCF HTTP конечная точка становится доступной для клиентов, не являющихся SOAP. Могут возникнуть ситуации, когда вы захотите сделать один и тот же контракт доступным в обоих случаях, в качестве конечной точки Web и конечной точки 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);
}
}
Присоединяясь ко всем сторонам, это будет наше определение system.serviceModel 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 .
Это то, что я сделал, чтобы это сработало. Убедитесь, что вы поместили
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>