2008-11-27 39 views
12

Tôi có một dịch vụ WCF với cấu hình sau:HTTP Request lỗi Bad khi yêu cầu một hợp đồng dịch vụ 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> 

Khi lưu trữ các dịch vụ trong quá trình WcfSvcHost.exe, nếu tôi duyệt đến URL:

http://localhost/myservice/contract

nơi các siêu dữ liệu dịch vụ có sẵn tôi nhận được một HTTP 400 Yêu cầu không hợp lệ lỗi.

Bằng cách kiểm tra các bản ghi WCF tôi phát hiện ra rằng một System.Xml.XmlException ngoại lệ được ném với thông điệp: "Phần nội dung của thông điệp không thể được đọc bởi vì nó là trống"
Dưới đây là một trích của tập tin log:

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

Nếu tôi thay vì duyệt đến URL:

http://localhost/myservice?wsdl

mọi thứ hoạt động tốt và tôi nhận được hợp đồng WSDL. Tại thời điểm này, tôi cũng có thể xóa hoàn toàn điểm cuối của siêu dữ liệu "MetadataHttp" và nó sẽ không tạo ra bất kỳ sự khác biệt nào.

Tôi đang sử dụng .NET 3.5 SP1. Có ai có ý tưởng về những gì có thể sai ở đây không?

+1

Tôi cũng đã thấy hành vi này khi tôi sử dụng nhiều điểm cuối. Không bao giờ tìm thấy câu trả lời: ( – leppie

+5

Tôi nghĩa là ghét WCF ... – Jammer

Trả lời

12

Tôi nghĩ rằng tôi đã tìm ra vấn đề là gì.

Nếu tôi duyệt đến URL:

http://localhost/myservice/contract

với ứng dụng WcfTestClient tôi có thể lấy thành công siêu dữ liệu dịch vụ.
Vì vậy, lỗi thực sự chỉ xảy ra khi tôi yêu cầu URL thông qua trình duyệt web.

Yêu cầu lỗi HTTP lỗi xuất phát từ thực tế là trình duyệt đưa ra yêu cầu HTTP GET trong đó nội dung của thư nằm trong tiêu đề HTTP và nội dung trống.
Đây chính xác là những gì WCF mexHttpBinding đang phàn nàn!

Để có được hợp đồng dịch vụ thông qua một trình duyệt web, bạn sẽ phải kích hoạt một cách rõ ràng trong các hành vi dịch vụ:

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

URL để yêu cầu trở nên thì:

http://localhost/myservice?wsdl

Vì vậy, hóa ra tôi hơi quá nhanh khi đăng câu hỏi này.Tuy nhiên, tôi sẽ giữ nó dù sao cũng chỉ để ghi lại.

+0

Tôi đã gặp vấn đề tương tự này, hóa ra tôi không thêm điểm cuối của dịch vụ vào web.config prod của tôi –

3

Tôi có thể khắc phục sự cố "400 yêu cầu không hợp lệ" bằng cách chuyển dịch vụ WCF của tôi khỏi máy chủ Visual Studio Development Server bằng máy chủ Local IIS Web (nhấp chuột phải vào dự án -> thuộc tính -> tab web -> nút radio trong "Máy chủ"). Tôi hy vọng điều này sẽ giúp một người nào đó ra khỏi đó bởi vì nó đã cho tôi hai ngày để con số này ra.

4

Nói chung đây là vấn đề với kích thước của phong bì SOAP. Kiểm tra cấu hình ràng buộc của bạn để thay đổi MaxBufferPoolSize, MaxReceivedMessageSize để cho phép nội dung lớn. Hãy nhớ rằng, bạn phải thay đổi cả hai phía máy khách và máy chủ.

Một vấn đề khác là MessageEnconding (một tham số ràng buộc khác), đảm bảo rằng phía máy khách và máy chủ đang sử dụng cùng một mã hóa.

Cuối cùng, hãy kiểm tra thông số Thuộc tính của thẻ trình đọc.

1

Nếu bạn không chắc chắn lý do tại sao mã WCF của bạn đang ném một lỗi thì tôi khuyên bạn nên sử dụng Trình theo dõi dịch vụ MS. Nó rất hữu ích trong việc xác định các vấn đề giao tiếp và vận chuyển như thế này. Hãy xem bài viết C# Corner này để biết thêm chi tiết.

2

Tôi đã gặp sự cố HTTP 400 khi sử dụng URL mex HTTPS từ SvcUtil, eventhough httpsGetEnabled được đặt thành true. Thông báo lỗi là dặm từ những gì thực sự là vấn đề vì vậy tôi đăng ở đây trong tình cờ trường hợp bất cứ ai khác trên cùng một vấn đề.

Tôi có chứng chỉ CA tự ký (TestRootCA) là tổ chức phát hành chứng chỉ máy chủ (máy chủ cục bộ). Trên máy khách, tôi đã nhập tệp CER TestRootCA nhưng tôi đã không nhập CRL (Danh sách Thu hồi Chứng chỉ). Có vẻ như khi bạn sử dụng CA tự ký, bạn phải cũng nhập CRL, nếu không xác thực máy chủ không thành công theo cách lạ, không ai trong số đó dẫn bạn đến vấn đề thực. Điều tồi tệ hơn là lỗi xảy ra trong quá trình bắt tay SSL, trước khi yêu cầu thậm chí đến dịch vụ của bạn, vì vậy bạn sẽ không thấy lỗi trong nhật ký theo dõi WCF.

Các vấn đề liên quan