2011-04-05 184 views
8

我正在尋找使用WCF REST服務應用程序模板來託管所有RESTful Web服務,但是,我也希望能夠使用SOAP端點公開我的WCF服務。WCF 4 - Soap和REST端點

我可以輕鬆地獲得我的WCF RESTful服務在WCF 4個工作使用下面的例子:http://christopherdeweese.com/blog2/post/drop-the-soap-wcf-rest-and-pretty-uris-in-net-4

這可能嗎?我會想象在Global.asax中應該有一種方法來連接其他端點並指定是否使用basicHttpBinding。我是否需要不使用WCF REST服務應用程序模板並創建標準的服務應用程序並通過配置將其連接起來?

感謝您的任何幫助。

+0

您是否曾嘗試向該模板添加「正常」服務? – 2011-04-05 13:53:52

+0

您能澄清一下,您是否試圖提供2個端點,SOAP和REST,或者您想要一個發送SOAP的RESTful服務?如果你的意思是第一,我的答案就會改變,因爲我相信你的意思是第二。 – Aliostad 2011-04-05 15:05:00

+0

我的目標是擁有一個具有2個端點(SOAP和REST)的WCF服務。 – Brandon 2011-04-06 13:25:25

回答

6

儘管在大多數情況下,我不會混用REST和SOAP端點,但我同意在某些情況下它是必需的。問題的答案是:可以混合使用。有兩個選項可以使用:

在Global.asax.cs中的調用,它定義了REST端點

`RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1)))` 

在地址/服務1基本上是定義一個服務的路線。您可以添加一個新的「服務」,使用相同的服務實現的,但使用不同的服務主機工廠(而不是使用WebServiceHostFactory,它定義了一個REST端點,你會用你自己的):

public class SoapServiceHostFactory : ServiceHostFactory 
{ 
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
     ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses); 
     ServiceMetadataBehavior smb = host.Description.Behaviors.Find<ServiceMetadataBehavior>(); 
     if (smb == null) 
     { 
      smb = new ServiceMetadataBehavior(); 
      host.Description.Behaviors.Add(smb); 
     } 

     smb.HttpGetEnabled = true; 
     host.AddServiceEndpoint(serviceType, new BasicHttpBinding(), "soap"); 
     return host; 
    } 
} 

而且在Global.asax.cs中,的RegisterRoutes:

private void RegisterRoutes() 
    { 
     // Edit the base address of Service1 by replacing the "Service1" string below 
     RouteTable.Routes.Add(new ServiceRoute("Service1", new WebServiceHostFactory(), typeof(Service1))); 

     RouteTable.Routes.Add(new ServiceRoute("SoapService", new SoapServiceHostFactory(), typeof(Service1))); 
    } 
  • 如果你確實想擁有一個「邏輯」的服務有兩個端點(我不推薦,因爲以前的方法是很簡單的),你可以再次創建一個自定義的ServiceHostFactory,然後在該工廠中添加兩個端點:一個用於REST(使用WebHttp綁定/ WebHttpBehavior),一個用於SOAP(例如使用BasicHttpBinding)。
+0

這實際上是完美的,因爲我有一個Global.asax,用於連接我的REST服務。 – Brandon 2011-05-17 16:39:11

+0

我出現錯誤:「無法將值添加到集合中,因爲集合已經包含相同的類型:'System.ServiceModel.Description.ServiceMetadataBehavior'。這個集合只支持每種類型的一個實例。「這有什麼問題? – fiberOptics 2012-02-16 08:07:05

+0

在這個例子中,SoapServiceHostFactory是爲描述添加一個ServiceMetadataBehavior,但在你的情況下你已經有了它(可能來自配置中的一些默認端點)。即使在這種情況下,我也更新了代碼片段。 – carlosfigueira 2012-02-16 14:55:41

0

我有一個Web服務正在運行,客戶端需要SOAP和REST訪問權限。您可以使用WebGet和WebInvoke屬性定義您的REST URL模板。

[ServiceContract] 
public interface IService 
{ 
    [OperationContract] 
    [WebInvoke(BodyStyle = WebMessageBodyStyle.Bare, RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)] 
    RS DoSomething(RQ request); 
} 

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)] 
public class Service : IService 
{ 
    public RS DoSomething(RQ rq) 
    { 
     return new RS(rq); 
    } 
} 

然後簡單地在配置

<system.serviceModel> 
    <services> 
     <service name="Service" behaviorConfiguration="defaultBehavior"> 
     <endpoint address="soap11" binding="basicHttpBinding" contract="IService" behaviorConfiguration="soapBehavior" /> 
     <endpoint address="rest" binding="webHttpBinding" contract="IService" behaviorConfiguration="restBehavior"/> 
     </service> 
    </services> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="restBehavior"> 
      <webHttp faultExceptionEnabled="true" /> 
     </behavior> 
     <behavior name="soapBehavior"> 
     </behavior> 
     </endpointBehaviors> 
     <serviceBehaviors> 
     <behavior name="defaultBehavior"> 
      <serviceMetadata httpGetEnabled="true" /> 
      <serviceDebug includeExceptionDetailInFaults="true" /> 
     </behavior> 
     </serviceBehaviors> 
    </behaviors> 
    </system.serviceModel> 
2

我不得不這樣它就會根據該接口的端點,而不是服務本身添加一個構造函數來carlosfigueira工廠所需的端點映射:

public class SoapServiceHostFactory : ServiceHostFactory 
{ 
    private Type serviceInterfaceType; 

    public SoapServiceHostFactory(Type serviceInterfaceType) 
    { 
     this.serviceInterfaceType = serviceInterfaceType; 
    } 

    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses) 
    { 
     ServiceHost host = base.CreateServiceHost(serviceType, baseAddresses); 
     host.Description.Behaviors.Add(new ServiceMetadataBehavior { HttpGetEnabled = true }); 
     host.AddServiceEndpoint(serviceInterfaceType, new BasicHttpBinding(), "soap"); 
     return host; 
    } 
} 
+0

謝謝!我還得到了一個異常,例如'合同類型MyClassSvc沒有被賦予ServiceContractAttribute。爲了定義一個有效的契約,指定的類型(契約接口或服務類)必須使用ServiceContractAttribute.'奇怪,因爲我的服務從接口繼承,並且接口具有該屬性。框架錯誤? – DeepSpace101 2012-02-17 18:28:22