2012-06-21 33 views
0

我之所以要求這是另一個問題,是因爲我使用Castle Windsor 3.0作爲我的DI框架,從而通過CW的WCF工具配置我的端點。我無法使用此設置找到任何解決方案。(Another)遠程服務器返回了一個意外的響應:(400)Bad Request - Castle Windsor,WCF


::更新::

感謝您的意見。

該項目是一個標準的WCF服務應用程序,它提供了許多連接到底層函數(SQl服務器等)的標準類庫。 項目中存在的Web服務是標準的Wcf服務(.svc),並將託管在IIS中(在默認的VS調試服務器中測試)將由ASP.NET MVC3 Web應用程序使用。

服務在客戶端和服務端均被連接到Windsor Container。

服務側:

<%@ ServiceHost 
Language="C#" 
Debug="true" 
Service="FileDownloadService" 
CodeBehind="FileDownloadService.svc.cs" 
Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory, 
    Castle.Facilities.WcfIntegration" %> 

因此,溫莎WCFacility負責所有依賴注入分辨率在兩個MVC3應用程序,和WCF服務應用程序。

我擔心配置的主要原因(我知道它使用了我從表單教程/演練/ SO問題獲得的值),因爲我不確定Windsor是否100%在服務端選擇了此配置 - 意見呢?

我也更新了代碼片段以顯示當前的impl。

[DataContract] 
    public enum FileTypeEnum 
    { 
     [EnumMember] 
     Generic = 1, 

     [EnumMember] 
     TXT = 2, 

     [EnumMember] 
     XLS = 3, 

     [EnumMember] 
     PDF = 4, 

     [EnumMember] 
     DOC = 5 
    } 

Web服務的解決方案,這有WCF Web服務,定義了以下合約:

[ServiceContract] 
public interface IFileDownloadService 
{ 
    [OperationContract] 
    FileDownloadReturnMessage DownloadFile(FileDownloadMessage request); 
} 

返回類型的合同是:

[MessageContract] 
public class FileDownloadReturnMessage : IDisposable 
{ 
    public FileDownloadReturnMessage(FileMetaData metaData, Stream stream) 
    { 
     FileByteStream = stream; 
    } 

    [MessageBodyMember(Order = 1)] 
    public Stream FileByteStream; 

    [MessageHeader(MustUnderstand = true)] 
    public FileMetaData DownloadedFileMetadata; 

    public void Dispose() 
    { 
     if (FileByteStream != null) 
     { 
      FileByteStream.Close(); 
      FileByteStream = null; 
     } 
    } 

和請求合同是:

[MessageContract] 
public class FileDownloadMessage 
{ 
    [MessageHeader(MustUnderstand = true)] 
    public FileMetaData FileMetaData; 
} 

和:

[DataContract(Namespace = "http://schemas.acme.it/2009/04")] 
public class FileMetaData 
{ 
    public FileMetaData(string fileName, string remoteFilePath) 
    { 
     FileName = fileName; 
     RemoteServerFilePath = remoteFilePath; 
     FileType = FileTypeEnum.Generic; 
    } 

    public FileMetaData(string fileName, string remoteFilePath, FileTypeEnum? fileType) 
    { 
     FileName = fileName; 
     RemoteServerFilePath = remoteFilePath; 
     FileType = fileType; 
    } 

    [DataMember(Name = "FileType", Order = 0, IsRequired = true)] 
    public FileTypeEnum? FileType; 

    [DataMember(Name = "FileName", Order = 1, IsRequired = true)] 
    public string FileName; 

    [DataMember(Name = "RemoteFilePath", Order = 2, IsRequired = true)] 
    public string RemoteServerFilePath; 
} 

服務器的溫莎上的配置注入的服務是:

.Register(Component.For<IFileDownloadService>() 
     .ImplementedBy<FileDownloadService>() 
     .Named("FileDownloadService") 
     .AsWcfService(new DefaultServiceModel() 
     .AddEndpoints(WcfEndpoint 
       .BoundTo(new BasicHttpBinding 
        { 
         MaxReceivedMessageSize = 2147483647, 
         MaxBufferSize = 2147483647, 
         MaxBufferPoolSize = 2147483647, 
         TransferMode = TransferMode.Streamed, 
         MessageEncoding = WSMessageEncoding.Mtom, 
         ReaderQuotas = new XmlDictionaryReaderQuotas 
          { 
           MaxDepth = 2147483647, 
           MaxArrayLength = 2147483647, 
           MaxStringContentLength = 2147483647, 
           MaxNameTableCharCount = 2147483647, 
           MaxBytesPerRead = 2147483647 
          } 
        })) 
       .Hosted() 
       .PublishMetadata()) 
     .LifeStyle.PerWcfOperation()) 

和端點的客戶端配置爲:

_container.Register(Component.For<IFileDownloadService>() 
        .AsWcfClient(new DefaultClientModel 
         { 
          Endpoint = WcfEndpoint 
           .BoundTo(new BasicHttpBinding 
            { 
             MaxReceivedMessageSize = 2147483647, 
             MaxBufferSize = 2147483647, 
             MaxBufferPoolSize = 2147483647, 
             TransferMode = TransferMode.Streamed, 
             MessageEncoding = WSMessageEncoding.Mtom, 
             ReaderQuotas = new XmlDictionaryReaderQuotas 
              { 
               MaxDepth = 2147483647, 
               MaxArrayLength = 2147483647, 
               MaxStringContentLength = 2147483647, 
               MaxNameTableCharCount = 2147483647, 
               MaxBytesPerRead = 2147483647 
              } 
            }) 
           .At(ConfigurationManager.AppSettings["FileDownloadAddress"]) 
          })); 

據因爲我知道這些端點配置必須匹配,他們會這樣做。但由於某些原因擊中方法:

var commandResult = _downloadService.DownloadFile(command); 

結果與以下堆棧跟蹤的異常:

Ex Message:  The remote server returned an unexpected response: (400) Bad Request. 
Source:  Castle.Facilities.WcfIntegration 
Target Site: Castle.Facilities.WcfIntegration.Proxy.WcfRemotingInterceptor+<>c__DisplayClass1 -> Void <PerformInvocation>b__0(Castle.Facilities.WcfIntegration.WcfInvocation) 
Stack Trace: at Castle.Facilities.WcfIntegration.Proxy.WcfRemotingInterceptor.<>c__DisplayClass1.<PerformInvocation>b__0(WcfInvocation wcfInvocation) 
    at Castle.Facilities.WcfIntegration.Proxy.WcfRemotingInterceptor.ApplyChannelPipeline(Int32 policyIndex, WcfInvocation wcfInvocation, Action`1 action) 
    at Castle.Facilities.WcfIntegration.Proxy.WcfRemotingInterceptor.<>c__DisplayClass4.<ApplyChannelPipeline>b__3() 
    at Castle.Facilities.WcfIntegration.WcfInvocation.Proceed() 
    at Castle.Facilities.WcfIntegration.RepairChannelPolicy.Apply(WcfInvocation wcfInvocation) 
    at Castle.Facilities.WcfIntegration.Proxy.WcfRemotingInterceptor.ApplyChannelPipeline(Int32 policyIndex, WcfInvocation wcfInvocation, Action`1 action) 
    at Castle.Facilities.WcfIntegration.Proxy.WcfRemotingInterceptor.PerformInvocation(IInvocation invocation, IWcfChannelHolder channelHolder, Action`1 action) 
    at Castle.Facilities.WcfIntegration.Proxy.WcfRemotingInterceptor.PerformInvocation(IInvocation invocation, IWcfChannelHolder channelHolder) 
    at Castle.Facilities.WcfIntegration.Async.WcfRemotingAsyncInterceptor.PerformInvocation(IInvocation invocation, IWcfChannelHolder channelHolder) 
    at Castle.Facilities.WcfIntegration.Proxy.WcfRemotingInterceptor.Intercept(IInvocation invocation) 
    at Castle.DynamicProxy.AbstractInvocation.Proceed() 
    at Castle.Proxies.IWcfChannelHolderProxy_2.FakeDownloadTest(FakeDownloadTestRequest request) 
    at cpfe.DAL.Repositories.FileDownloadRepository.DownloadFile(IEnumerable`1 fileIds, TenantDTO tenant, String zipPackageName, UserDTO user) \..\..\..\FileDownloadRepository.cs:line 44 

沒有任何人有任何線索,爲什麼發生這種情況?

在此先感謝!

+0

瞭解一些關於您如何託管服務可能會有所幫助 - 我看到您將問題標記爲asp .net mvc,但您在描述中提到了一個Web服務項目 - 它是什麼類型的項目以及將要執行什麼操作在那裏關於配置容器,路線等?我只是使用幾個控制檯應用程序來嘗試@Hyralex答案,它運行良好,因此可以將其縮小到我認爲的服務主機。 – kmp

+0

@kmp - 更新了問題,歡呼聲。 – M05Pr1mty

+0

我們可以看到FileTypeEnum的合約嗎? – Hyralex

回答

2

我轉載400錯誤,它是在代碼做了一些更改後消失:

  1. 使用TransferMode = TransferMode.StreamedResponse,而不是Streamed。我只將它應用於客戶端配置。服務器仍然有Streamed
  2. 將默認(無參數)構造函數添加到FileDownloadReturnMessage。有必要對MessageContract進行反序列化。代碼 - public FileDownloadReturnMessage() { }

,現在我無法重現錯誤回來,一切工作正常,即使TransferMode.Streamed

讓我知道這是否有助於有趣的事情。

如果您仍然無法解決問題,我可以發佈我的代碼。

有趣的是,WCF在客戶端生成了400錯誤。如果您檢查提琴手中的流量,服務器始終會返回200和正確的數據。

+0

無論是1.還是2.它解決了這個問題。非常感謝。 – M05Pr1mty

+0

如果可能 - 您是否可以提供有關如何測試其是否已正確設置並充當流媒體服務的信息,或者是否以緩衝方式執行?謝謝。 – M05Pr1mty

+0

@ M05Pr1mty在fiddler或類似軟件中檢查HTTP消息頭。它應該有「傳輸編碼:分塊」。 –

0

請在服務端檢查您的連接字符串。如果您在連接字符串中使用Windows身份驗證,請嘗試通過爲您的數據庫創建SQL用戶來使用SQL身份驗證

+0

道歉,如果我誤解,但這是如何相關?該服務不會執行任何數據庫操作,甚至不會觸摸我的ORM。 Web服務也不是使用需要Windows身份驗證或其他方式的傳輸或消息安全保護的。 – M05Pr1mty

+0

@ M05Pr1mty因爲在堆棧跟蹤它顯示在cpfe.DAL.Repositories ...所以從這裏我認爲數據庫涉及到您的服務。當我在連接字符串中使用Windows身份驗證時,我得到了與我的服務相同的400錯誤請求問題。 – Waqar

+0

更正 - 在這種情況下的存儲庫,包裝器調用底層WCF服務。因此數據源是WCF服務。 – M05Pr1mty

2

我認爲您不能在消息正文中傳輸流和其他數據。 您需要使用MessageContract在消息的頭部和正文中的流中添加自定義數據。

您需要使用特定合同。您可以使用帶有封裝您當前合同的messagecontract的類。像這樣:

[ServiceContract] 
public interface IFileDownloadService 
{ 
    [OperationContract] 
    StreamResponse DownloadFile(DownloadFileCommandRequest command); 
} 

[MessageContract] 
public class StreamResponse 
{ 
    [MessageHeader()] 
    public CommandResult<FileDownloadDTO> {get; set;} 

    [MessageBodyMember(Order = 1)] 
    public Stream FileByteStream { get; set; } 
} 

[MessageContract] 
public class DownloadFileCommandRequest 
{ 
    [MessageBodyMember(Order = 1)] 
    public DownloadFileCommand FileCommand {get; set;} 
} 

並刪除FileDownloadDTO類中的流屬性。也許如果你只刪除DataMember屬性就沒關係。

[DataContract] 
public class FileDownloadDTO : IDisposable, IDTOBase 
{ 
    [DataMember] 
    public string FileName { get; set; } 

    [DataMember] 
    public long Length { get; set; } 

    [DataMember] 
    public int Id { get; set; } 
} 

這裏是客戶端配置的例子。

<binding name="FileHttpBinding" closeTimeout="04:01:00" 
       openTimeout="04:01:00" receiveTimeout="04:10:00" sendTimeout="04:01:00" 
       allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" 
       maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" 
       transferMode="Streamed" messageEncoding="Mtom"> 
       <readerQuotas maxDepth="128" maxStringContentLength="2147483647" maxArrayLength="2147483647" 
         maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 
       <security mode="None"> 
       </security> 
      </binding> 
+0

這是100%正確的,我需要更新我的問題以反映昨天進行了一些更多閱讀後所做的這些更改。但是,即使使用MessageContracts,我仍然會發生同樣的錯誤。據我所知,這是Windsor的綁定和配置問題。 +1雖然正確,但問題仍然存在。 – M05Pr1mty

+0

@ M05Pr1mty我不認爲配置是問題,因爲我有相同的工作。嘗試一下,簡單地看看你的合同,看看它是否有問題。也許郵件頭太複雜。嘗試刪除泛型類型CommandResult <>。我編輯了我的迴應,將我的客戶端配置作爲例子。 – Hyralex

+0

更新了一些註釋的問題,以及當前的代碼狀態。歡呼的幫助。 – M05Pr1mty

相關問題