web-dev-qa-db-ja.com

WCFサービスコントラクトを要求するときのHTTP Bad Requestエラー

次の構成のWCFサービスがあります。

<system.serviceModel>
    <behaviors>
        <serviceBehaviors>
            <behavior name="MetadataEnabled">
                <serviceDebug includeExceptionDetailInFaults="true" />
                <serviceMetadata httpGetEnabled="true" />
            </behavior>
        </serviceBehaviors>
     </behaviors>
      <services>
          <service behaviorConfiguration="MetadataEnabled" name="MyNamespace.MyService">
              <endpoint name="BasicHttp"
                        address=""
                        binding="basicHttpBinding"
                        contract="MyNamespace.IMyServiceContract" />
              <endpoint name="MetadataHttp"
                        address="contract"
                        binding="mexHttpBinding" 
                        contract="IMetadataExchange" />
              <Host>
                  <baseAddresses>
                      <add baseAddress="http://localhost/myservice" />
                  </baseAddresses>
              </Host>
          </service>
    </services>
</system.serviceModel>

WcfSvcHost.exeプロセスでサービスをホストしているときに、URLを参照すると:

http:// localhost/myservice/contract

サービスメタデータが利用可能な場合、HTTP 400 Bad Requestエラーが発生します。

WCFログを調べると、System.Xml.XmlException例外が次のメッセージでスローされていることがわかりました: "メッセージの本文が空のため、本文を読み取ることができません。 "
ログファイルの抜粋を以下に示します。

<Exception>
<ExceptionType>
System.ServiceModel.ProtocolException, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
</ExceptionType>
<Message>There is a problem with the XML that was received from the network. See inner exception for more details.</Message>
<StackTrace>
at System.ServiceModel.Channels.HttpRequestContext.CreateMessage()
at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, ItemDequeuedCallback callback)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult result)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
<InnerException>
<ExceptionType>System.Xml.XmlException, System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</ExceptionType>
<Message>The body of the message cannot be read because it is empty.</Message>
<StackTrace>
at System.ServiceModel.Channels.HttpRequestContext.CreateMessage()
at System.ServiceModel.Channels.HttpChannelListener.HttpContextReceived(HttpRequestContext context, ItemDequeuedCallback callback)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContextCore(IAsyncResult result)
at System.ServiceModel.Channels.SharedHttpTransportManager.OnGetContext(IAsyncResult result)
at System.ServiceModel.Diagnostics.Utility.AsyncThunk.UnhandledExceptionFrame(IAsyncResult result)
at System.Net.LazyAsyncResult.Complete(IntPtr userToken)
at System.Net.LazyAsyncResult.ProtectedInvokeCallback(Object result, IntPtr userToken)
at System.Net.ListenerAsyncResult.WaitCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)
at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pOVERLAP)
</StackTrace>
</InnerException>
</Exception>

代わりにURLを参照した場合:

http:// localhost/myservice?wsdl

すべてが正常に動作し、WSDLコントラクトを取得します。この時点で、 "MetadataHttp"メタデータエンドポイントを完全に削除することもできますが、何の違いもありません。

.NET 3.5 SP1を使用しています。誰かがここで何が間違っているのか考えていますか?

13

何が問題か分かったと思います。

URLを参照すると:

http:// localhost/myservice/contract

WcfTestClientアプリケーションを使用すると、サービスメタデータを正常に取得できます。
そのため、エラーは本当に、Webブラウザーを介してURLを要求したときにのみ発生します。

HTTP Bad Requestエラーは、ブラウザがメッセージのコンテンツがHTTPヘッダーと本文にあるHTTP GETリクエストを発行するという事実から生じます空です。
これはまさにWCFmexHttpBindingが不満を言っていることです!

Webブラウザーを介してサービス契約にアクセスするには、サービス動作で明示的に有効にする必要があります。

<serviceBehaviors>
    <behavior name="MetadataEnabled">
        <serviceMetadata httpGetEnabled="true" />
    </behavior>
</serviceBehaviors>

要求するURLは次のようになります。

http:// localhost/myservice?wsdl

だから、私はこの質問を投稿するのが少し早すぎることがわかりました。ただし、とにかく記録のために保管しておきます。

12

一般に、これはSOAPエンベロープのサイズの問題です。MaxBufferPoolSize、MaxReceivedMessageSizeを変更して大量のコンテンツを許可するには、バインディング構成を確認してください。クライアント側とサーバー側の両方で変更する必要があることに注意してください。

別の問題はMessageEnconding(別のバインディングパラメーター)です。クライアント側とサーバー側が同じエンコーディングを使用していることを確認してください。

最後に、Reader Quotas Propertiesパラメータを確認します。

4
Luty

WCFサービスをVisual Studio Development Serverの実行からローカルIIS Webサーバーの使用(プロジェクトを右クリック->プロパティ)に切り替えることで、「400 Bad Request」問題を修正できました。 -> [Web]タブ-> [サーバー]の下のラジオボタン。

3
Bryan Denny

httpsGetEnabledtrueに設定されていても、SvcUtilからHTTPS mex URLを使用するとHTTP 400の問題が発生しました。エラーメッセージは実際の問題から何マイルも離れていたため、他の誰かが同じ問題に遭遇した場合に備えて、ここに投稿します。

サーバー証明書(localhost)の発行者である自己署名CA証明書(TestRootCA)がありました。クライアントでTestRootCA CERファイルをインポートしましたが、CRL(証明書失効リスト)はインポートしませんでした。自己署名CAを使用する場合はmustもCRLをインポートするようです。そうでない場合、サーバー認証が奇妙な方法で失敗し、いずれも実際の問題を示していません。さらに悪いことに、SSLハンドシェイク中に失敗が発生し、リクエストがサービスに到達するまでbeforeであるため、WCFトレースログにエラーが表示されません。

2
Boris B.

WCFコードがエラーをスローする理由がわからない場合は、MS Service Trace Viewerを強くお勧めします。このような通信とトランスポートの問題を特定するのに非常に役立ちます。詳細については、この C#コーナー の記事を参照してください。

2
IsolatedStorage