【问题标题】:WCF 4 - Soap and REST endpointsWCF 4 - Soap 和 REST 端点
【发布时间】:2011-07-29 23:45:52
【问题描述】:

我正在考虑使用 WCF REST 服务应用程序模板来托管我的所有 RESTful Web 服务,但是,我还希望能够使用 SOAP 端点公开我的 WCF 服务。

我可以使用以下示例轻松让我的 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 服务应用程序模板并创建标准服务应用程序并通过配置将其全部连接起来?

感谢您的帮助。

【问题讨论】:

  • 您是否尝试向该模板添加“正常”服务?
  • 您能否澄清一下您正在尝试提供 2 个端点,SOAP 和 REST,或者您想要一个发送 SOAP 的 RESTful 服务?如果你的意思是第一个,我的答案会改变,因为我相信你的意思是第二个。
  • 我的目标是拥有一个具有 2 个端点 SOAP 和 REST 的 WCF 服务。

标签: c# .net wcf soap


【解决方案1】:

虽然在大多数情况下我不会混合使用 REST 和 SOAP 端点,但我同意在某些情况下这是必要的。问题的答案:是的,可以混合使用。您可以使用两个选项:

Global.asax.cs 中定义 REST 端点路由的调用

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

本质上定义了地址/Service1 处的服务。您可以添加一个新的“服务”,使用相同的服务实现,但使用不同的服务主机工厂(而不是使用定义 REST 端点的 WebServiceHostFactory,您可以使用自己的):

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(使用 WebHttpBinding/WebHttpBehavior),一个用于 SOAP(例如,使用 BasicHttpBinding)。

【讨论】:

  • 这实际上是完美的,因为我有一个 Global.asax,我正在其中连接我的 REST 服务。
  • 我遇到错误:“无法将值添加到集合中,因为集合已包含相同类型的项目:'System.ServiceModel.Description.ServiceMetadataBehavior'。此集合每种类型只支持一个实例。”这有什么问题?
  • 此示例中的SoapServiceHostFactory 是在描述中添加ServiceMetadataBehavior,但在您的情况下,您已经拥有它(可能来自配置中的某个默认端点)。即使在这种情况下,我也更新了代码 sn-p。
【解决方案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;
    }
}

【讨论】:

  • 谢谢!我也遇到了The contract type MyClassSvc is not attributed with ServiceContractAttribute. In order to define a valid contract, the specified type (either contract interface or service class) must be attributed with ServiceContractAttribute. Weird 之类的异常,因为我的服务继承自接口并且接口具有该属性。框架错误?
【解决方案3】:

我有一个 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>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    相关资源
    最近更新 更多