0

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 パラメータは、最大で 1 つです。余分なボディ パラメーターを削除するか、WebGetAttribute/WebInvokeAttribute の BodyStyle プロパティを Wrapped に設定します。

ここで、Finalize 操作は .NET クライアント経由でのみ呼び出されるようにし、GetPayment 操作は任意のブラウザーから呼び出されるようにします。

4

1 に答える 1

0

Finalize メソッドを webhttp エンドポイント経由で接続しているクライアントから呼び出したくない場合、および GetPayments を wshttp 経由で接続しているクライアントから呼び出したくない場合は、単純にコントラクトを 2 つに分割できます。

IIS でホストしていると仮定すると、それが機能することを確認するためにちょっとしたトリックが必要になる場合があります。質問の詳細を使用して例を挙げましょう...

まず最初に、2 つのサービスのコードを示します...

[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
}

次のように 2 つの .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 メソッドが呼び出されます。

于 2012-04-23T19:41:56.110 に答える