WCF服务的REST / SOAP端点


425

我有一个WCF服务,我想将它同时作为RESTfull服务和SOAP服务公开。有人做过这样的事吗?


好问题和好答案。
chandra rv

Answers:


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

REST Plain Old XML的POX行为

<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
当我在某个虚拟目录(如someserver / myvirtualdir / service.svc)中的IIS中托管.svc时,它的外观如何?我应该如何访问?
Sunny Milenov

我想更进一步,并为JSON地址添加到HTTPS的绑定。我怎么做? stackoverflow.com/questions/18213472/…–
史蒂夫·

这是指当我尝试引用我的服务接口时,我的合同IEvents无效:<service name =“ Events”> <端点地址=“ json” binding =“ webHttpBinding” behaviorConfiguration =“ jsonBehavior” contract =“ IEvents” />。我的IEvents在界面上具有[ServiceContract]属性,因此不确定原因。</ service>
PositiveGuy

我可以让localhost:44652 / MyResource / json正常工作,但无法获取ID即可工作localhost:44652 / MyResource / 98 / json。我尝试添加一个UriTemplate为“ / {id}”,也尝试了“ events / {id},但是当我尝试访问该服务时找不到它。只有前一个有效,不确定如何获取后者上班
PositiveGuy

2
那里没有物理文件怎么办?我似乎只收到404错误,一定是缺少了一些东西
RoboJ1M 2014年

39

这个帖子已经有一个很好的答案通过“社区维基”,我也建议看看里克施特拉尔的网络博客,大约有WCF休息多好职位像这样

我都使用了这两种MyService服务...然后可以使用jQuery的REST接口或Java的SOAP接口。

这是从我的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){
    //...

我很想知道您相信添加这些WebGet和WebInvoke属性会带来什么好处。
Darrel Miller

2
您可以通过浏览器发出请求: localhost / MyService.svc / MyXmlResource / test 并明确表示格式Json或Xml。如果你想同样的方法皆响应,这里是一个链接: blogs.msdn.com/dotnetinterop/archive/2008/11/04/...
图奥马斯Hietanen

这是出于测试目的。只是看看您的端点是否正常工作。您看过SoapUI吗? soapui.org
Darrel Miller 2010年

@TuomasHietanen-我没有通过使用webHttp行为获得JSON类型响应,但是使用enableWebScript我确实获得了JSON类型响应。我确实将ResponseFormat设置为WebMessageFormat.Json。另一方面,如果使用enableWebScript行为,则不能使用URItemplate。有任何想法吗?
smile.al.d.way 2011年

1
@CoffeeAddict-为什么要使用界面?只是要有界面?您永远不会重复使用此接口。这比较简单。
Tuomas Hietanen

25

如果您只想开发一个Web服务并将其托管在许多不同的端点上(即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输出(当使用具有Accept:text / html的HTTP客户端(例如,浏览器)进行调用时),因此您可以更好地可视化服务的输出。

处理不同的REST动词也很简单,这是C#1页中完整的REST服务CRUD应用程序(比配置WCF要少;):


7

MSDN现在似乎对此有一篇文章:

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

介绍:

默认情况下,Windows Communication Foundation(WCF)使端点仅对SOAP客户端可用。在如何:创建基本WCF Web HTTP服务中,使端点可用于非SOAP客户端。有时候,您可能想使两种合同都可以作为Web端点和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>

在行为之后,下一步是绑定。例如,对SOAP端点的basicHttpBinding 和对REST的 webHttpBinding 。

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

为了测试这两个端点,我们可以使用WCFClientSOAP邮递员REST


工作正常,如预期
Shiv

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>
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.