WCF多个端点不起作用

时间:2012-04-22 08:29:43

标签: wcf

我试图让我的WCF服务具有可以通过代理客户端和REST调用调用的操作,我使用以下配置:

<services>
  <service behaviorConfiguration="SecureBehavior" name="Payment">
    <endpoint address="" binding="wsHttpBinding"  bindingConfiguration="secureWS" contract="IPayment"/>
    <endpoint address="rest" binding="webHttpBinding" behaviorConfiguration="webBehavior" contract="IPayment"/>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
  <bindings>
    <mexHttpBinding>
      <binding name="userMex"/>
    </mexHttpBinding>
    <wsHttpBinding>
      <binding name="secureWS">
        <security mode="Message">
          <message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true"/>
        </security>
      </binding>
      <binding name="publicWS">
        <security mode="None"/>
      </binding>
    </wsHttpBinding>
  </bindings>
  <behaviors>
    <serviceBehaviors>
      <behavior name="SecureBehavior">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="true"/>
        <serviceCredentials>
          <windowsAuthentication allowAnonymousLogons="false"/>
        </serviceCredentials>
      </behavior>
      <behavior name="PublicBehavior">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="true"/>
        <serviceCredentials>
          <windowsAuthentication allowAnonymousLogons="true"/>
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
    <endpointBehaviors>
      <behavior name="webBehavior">
        <webHttp/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
</services>

这是我的代码:

[ServiceContract]
public interface IPayment
{
    [OperationContract]
    PaymentResult Finalize(string TransactionID, string CertificatePath);

    [OperationContract]
    [WebGet(UriTemplate = "rest")]
    System.IO.Stream GetPayment();
}

现在每当我运行我的服务时,我都会收到此错误:

  

合同'IPayment'的操作'Finalize'指定要序列化的多个请求体参数,而不包含任何包装元素。最多可以在没有包装元素的情况下序列化一个body参数。删除额外的body参数或将WebGetAttribute / WebInvokeAttribute上的BodyStyle属性设置为Wrapped。

在这里我想保持Finalize操作只能通过.NET客户端调用,并且GetPayment操作可以通过任何浏览器调用。

1 个答案:

答案 0 :(得分:0)

如果您不希望从通过webhttp端点连接的客户端调用Finalize方法,并且您不希望从通过wshttp连接的客户端调用GetPayments,则可以简单地将合同分成两部分。

假设您在IIS中托管,您可能需要做一些小技巧以确保它有效。让我举一个使用问题细节的例子......

首先,这里是两个服务的代码......

[ServiceContract]
public interface IPayment
{
    [OperationContract]
    [WebGet(UriTemplate = "rest")]
    System.IO.Stream GetPayment();
}

[DataContract]
public class PaymentResult
{
}

[ServiceContract]
public interface IMakePayment
{
    [OperationContract]
    PaymentResult Finalize(string TransactionID, string CertificatePath);
}

// Maybe you really should have the two services separate but if you do
// want to implement them both in a single class you can do this
public abstract class PaymentBase : IMakePayment, IPayment
{
    // ... Implement both interfaces here
    public PaymentResult Finalize(string TransactionID, string CertificatePath)
    {
        return null;
    }

    public System.IO.Stream GetPayment()
    {
        return null;
    }
}

public class MakePayment : PaymentBase
{
    // Empty
}

public class Payment : PaymentBase
{
    // Empty
}

现在创建两个.svc文件,如下所示:

<强> MakePayment.svc

<%@ ServiceHost Language="C#" Debug="true" Service="WebApplication1.MakePayment"  %>

<强> Payment.svc

<%@ ServiceHost Language="C#" Debug="true" Service="WebApplication1.Payment" %>

最后这里是system.servicemodel配置:

<system.serviceModel>
  <services>      
    <service behaviorConfiguration="SecureBehavior" name="WebApplication1.MakePayment">        
      <endpoint binding="wsHttpBinding" bindingConfiguration="secureWS" contract="WebApplication1.IMakePayment"/>
      <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" bindingConfiguration="userMex"/>
    </service>
    <service behaviorConfiguration="PublicBehavior" name="WebApplication1.Payment">
      <endpoint binding="webHttpBinding" behaviorConfiguration="webBehavior" bindingConfiguration="publicWS" contract="WebApplication1.IPayment"/>
    </service>      
  </services>
  <bindings>
    <mexHttpBinding>
      <binding name="userMex"/>
    </mexHttpBinding>
    <wsHttpBinding>
      <binding name="secureWS">
        <security mode="Message">
          <message clientCredentialType="Windows" negotiateServiceCredential="true" establishSecurityContext="true"/>
        </security>
      </binding>
    </wsHttpBinding>
    <webHttpBinding>
      <binding name="publicWS">
        <security mode="None"/>
      </binding>
    </webHttpBinding>
  </bindings>
  <behaviors>
    <serviceBehaviors>
      <behavior name="SecureBehavior">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="true"/>
        <serviceCredentials>
          <windowsAuthentication allowAnonymousLogons="false"/>
        </serviceCredentials>
      </behavior>
      <behavior name="PublicBehavior">
        <serviceMetadata httpGetEnabled="true"/>
        <serviceDebug includeExceptionDetailInFaults="true"/>
        <serviceCredentials>
          <windowsAuthentication allowAnonymousLogons="true"/>
        </serviceCredentials>
      </behavior>
    </serviceBehaviors>
    <endpointBehaviors>
      <behavior name="webBehavior">
        <webHttp/>
      </behavior>
    </endpointBehaviors>
  </behaviors>
  <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

你去 - 如果你连接到/MakePayment.svc你将通过WSHTTP连接并能够调用FinalizePayment,如果你去/Payments.svc/rest它会调用GetPayment方法返回一个流。