0

これを他の多くの人とは別の質問として尋ねる理由は、Castle Windsor 3.0をDIフレームワークとして使用しているため、CWのWCFファシリティを介してエンドポイントを構成しているためです。この設定では解決策が見つかりません。


:: アップデート ::

コメントありがとうございます。

このプロジェクトは、標準のWCFサービスアプリケーションであり、基盤となる機能(SQlサーバーなど)に接続する多数の標準クラスライブラリを提供します。プロジェクトに存在するWebサービスは標準のWcfサービス(.svc)であり、IISでホストされ(デフォルトのVSデバッグサーバーでテストされます)、ASP.NETMVC3Webアプリケーションによって使用されます。

サービスは、このクライアント側とサービス側の両方でWindsorContainerにフックされます。

サービス側:

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

したがって、Windsor 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
    }

WCF Webサービスを含む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;
}

Windsorインジェクションサービスのサーバーでの構成は次のとおりです。

.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

なぜこれが起こっているのかについて誰かが何か手がかりを持っていますか?

前もって感謝します!

4

3 に答える 3

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>
于 2012-06-26T10:12:57.583 に答える
2

400 エラーを再現しましたが、コードにいくつかの変更を加えた後、エラーはなくなりました。

  1. TransferMode = TransferMode.StreamedResponse,の代わりに使用しStreamedます。私はそれをクライアント構成にのみ適用しました。サーバーにはまだStreamed.
  2. デフォルト (パラメーターなし) コンストラクターを に追加しますFileDownloadReturnMessageMessageContractデシリアライズに必要です。コード -public FileDownloadReturnMessage() { }

面白いことに、エラーを再現できず、すべて正常に動作しますTransferMode.Streamed

それが役に立ったかどうか教えてください。

それでも問題を解決できない場合は、コードを公開できます。

興味深いのは、クライアントで WCF によって 400 エラーが生成されることです。フィドラーでトラフィックをチェックすると、サーバーは常に 200 と正しいデータを返します。

于 2012-06-26T17:49:55.350 に答える
0

サービス側で接続文字列を確認してください。接続文字列で Windows 認証を使用している場合は、データベースに sql ユーザーを作成して SQL 認証を使用してみてください。

于 2012-06-25T10:51:42.393 に答える