2011-04-05 190 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