WCF 服务的 REST / SOAP 端点

Posted

技术标签:

【中文标题】WCF 服务的 REST / SOAP 端点【英文标题】:REST / SOAP endpoints for a WCF service 【发布时间】:2010-09-16 05:50:26 【问题描述】:

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

【问题讨论】:

好问题和好答案。 【参考方案1】:

您可以在两个不同的端点中公开服务。 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>

所以,该服务将在

http://www.example.com/soap http://www.example.com/json

对操作合约应用 [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 的 POX 行为普通旧 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>

服务将在

http://www.example.com/soap http://www.example.com/xml

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

另一种方法是公开两个不同的服务合同,每个合同都有特定的配置。这可能会在代码级别生成一些重复项,但最终,您希望使其正常工作。

【讨论】:

当我将 .svc 托管在 IIS 中的某个虚拟目录(如 someserver/myvirtualdir/service.svc)中时,情况如何?我应该如何访问它? 我想更进一步,为 JSON 地址添加到 HTTPS 的绑定。我怎么做? ***.com/questions/18213472/… 当我尝试引用我的服务接口时,我的合同 IEvents 无效:。我的 IEvents 在界面上有一个 [ServiceContract] 属性,所以不知道为什么。 服务> 我可以让localhost:44652/MyResource/json 工作,但我无法获得工作身份localhost:44652/MyResource/98/json。我尝试添加“/id”的 UriTemplate,也尝试过“events/id”但是当我尝试访问服务时找不到它。只有第一个有效,不知道如何获得后者工作。 那里没有物理文件如何工作?我似乎收到了 404 错误,一定是遗漏了什么【参考方案2】:

这篇文章已经得到了“社区维基”的很好的回答,我也推荐看看 Rick Strahl 的网络博客,有很多关于 WCF Rest 的好帖子,比如this。

我用这两种方法来获得这种 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 属性会获得什么好处。 您可以通过浏览器发出请求:localhost/MyService.svc/MyXmlResource/test 并明确说出格式 Json 或 Xml。如果您希望使用相同的方法来响应两者,这里有一个链接:blogs.msdn.com/dotnetinterop/archive/2008/11/04/… 这是为了测试目的。只是看看您的端点是否正常工作。你看过 SoapUI 吗? soapui.org @TuomasHietanen - 我没有通过使用 webHttp 行为获得 JSON 类型的响应,但是使用 enableWebScript 我确实获得了 JSON 类型的响应。我确实将 ResponseFormat 设置为 WebMessageFormat.Json。另一方面,如果我使用 enableWebScript 行为,我将无法使用 URItemplate。有什么想法吗? @CoffeeAddict - 为什么要使用接口?只是为了有接口?你永远不会重用这个接口。这更简单。【参考方案3】:

如果您只想开发单个 Web 服务并将其托管在许多不同的端点上(即 SOAP + REST,具有 XML、JSON、CSV、html 输出)。您还应该考虑使用 ServiceStack,我正是为此目的而构建的,您开发的每项服务都可以在 SOAP 和 REST 端点上自动提供,开箱即用,无需任何配置.

Hello World 示例展示了如何创建一个简单的 with 服务(无需配置):

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 立即使用:

肥皂 XML JSON HTML

它还内置了 a friendly HTML output(当使用具有 Accept:text/html 例如浏览器的 HTTP 客户端调用时),因此您能够更好地可视化您的输出服务。

处理不同的 REST 动词也很简单,这里有一个完整的 REST 服务 CRUD 应用程序,只需一页 C#(比配置 WCF 所需的时间少;):

Front-end TODO applicaiton Back-end REST Service implementation

【讨论】:

【参考方案4】:

MSDN 好像现在有这方面的文章:

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

简介:

默认情况下,Windows Communication Foundation (WCF) 使端点仅对 SOAP 客户端可用。在如何:创建基本 WCF Web HTTP 服务中,端点可供非 SOAP 客户端使用。有时您可能希望以两种方式提供相同的合同,作为 Web 端点和作为 SOAP 端点。本主题展示了如何执行此操作的示例。

【讨论】:

【参考方案5】:

我们必须定义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 端点。注意端点的address="",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>

要测试两个端点,我们可以使用 WCFClientSOAPPostManREST。 p>

【讨论】:

工作正常【参考方案6】:

这就是我为使其正常工作所做的。确保将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>

【讨论】:

以上是关于WCF 服务的 REST / SOAP 端点的主要内容,如果未能解决你的问题,请参考以下文章

WCF 休息和 Wcf 肥皂服务之间的区别

了解带有附件 (SwA) 的 WCF Multipart Soap 服务/端点

将 WCF SOAP 和 WCF REST 服务托管为 Azure 应用服务

如何同时使用 SOAP WCF 服务和 REST API

WCF 通过 MSMQ 到 WCF 请求和响应

WCF 服务默认是restful 还是基于soap?