2

我已经搜索了答案,但没有找到任何东西。我想我错过了一些简单的东西,但我不知道它是什么。

我已经向我们的一个 WCF 服务添加了一个方法,该方法应该返回一个流作为消息协定的一部分。但是,当我在客户端添加服务引用时,消息协定的流部分是字节数组,而不是流。我添加了基本相同的方法,但没有消息契约(这不是一个选项),并且那个方法是客户端的流。

服务合约

[ServiceContract(Name = "FileService", Namespace = "http://services.mycompanycom/Data/")]
public interface IFileService : IServiceBase
{
    [OperationContract( IsOneWay = false )]
    [FaultContract( typeof( ServiceException ), Name = "ServiceException", Namespace = "http://services.mycompanycom/Common/" )]
    FileStreamResponse GetFileStream( FileIDMessage message );

    [OperationContract( IsOneWay = false )]
    [FaultContract( typeof( ServiceException ), Name = "ServiceException", Namespace = "http://services.mycompanycom/Common/" )]
    Stream GetFileStream2( AuthTicket ticket, int FileID );
}

消息合约

[MessageContract]
public sealed class FileStreamResponse {
    [MessageHeader( MustUnderstand = true )]
    public string FileName { get; set; }
    [MessageHeader( MustUnderstand = true )]
    public bool IsZip { get; set; }
    [MessageHeader( MustUnderstand = true )]
    public long Length { get; set; }
    [MessageBodyMember( Order = 1 )]
    public Stream FileByteStream;
}

服务代码

这在客户端配置为返回字节数组:

[FaultContract( typeof( ServiceException ), Name = "ServiceException", Namespace = "http://services.mycompanycom/Common/" )]
public FileStreamResponse GetFileStream( FileIDMessage message ) {
    CheckRights( message.AuthTicket, message.FileID, EntityEnum.Blob );

    var blob = new BlobBroker( ).GetByPk( message.GetSecurityTicket( ), message.FileID );
    if( blob.PkBlob == 0 || blob.BlobData == null )
        throw ServiceUtilities.LogError( "File record not found.", "File record not found.", MethodBase.GetCurrentMethod( ) );
    var response = new FileStreamResponse {
                                              FileName = blob.FileName,
                                              IsZip = blob.IsZip,
                                              Length = blob.BlobData.Length,
                                              FileByteStream = new MemoryStream( blob.BlobData )
                                          };
    response.FileByteStream.Position = 0;
    return response;
}

这在客户端配置为流:

[FaultContract( typeof( ServiceException ), Name = "ServiceException", Namespace = "http://services.mycompanycom/Common/" )]
public Stream GetFileStream2( AuthTicket ticket, int FileID ) {
    var f = new FileIDMessage {
                                  FileID = FileID,
                                  AuthTicket = ticket
                              };
    return this.GetFileStream( f ).FileByteStream;
}

服务器配置

<system.serviceModel>
    <services>
        <service behaviorConfiguration="BasicServiceBehavior" name="MyCompany.Web.MyServices.FileService">
            <endpoint address="" behaviorConfiguration="secureEndpointBehavior"
                binding="basicHttpBinding" bindingConfiguration="StreamingBinding"
                contract="MyCompany.Web.MyServices.IFileService" />
        </service>
    </services>
    <bindings>
        <basicHttpBinding>
            <binding name="StreamingBinding" receiveTimeout="00:10:00"
                 sendTimeout="00:10:00" maxBufferSize="65536" maxReceivedMessageSize="2147483647" transferMode="StreamedResponse"
                 textEncoding="utf-8">
                <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
                     maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
                <security mode="None">
                    <transport clientCredentialType="None" />
                </security>
            </binding>
        </basicHttpBinding>
        <webHttpBinding>
            <binding name="webHttpBindingWithCrossDomain"/>
        </webHttpBinding>
    </bindings>
    <behaviors>
        <endpointBehaviors>
            <behavior name="secureEndpointBehavior" >
                <dataContractSerializer maxItemsInObjectGraph="2147483646" />
                <authorizationInspector /> 
                <operationLogger />
                <wsdlExtras location="http://localservices.mycompany.com/" exportXmlComments="false" singleFile="false" />
            </behavior>
        </endpointBehaviors>
        <serviceBehaviors>
            <behavior name="BasicServiceBehavior">
                <dataContractSerializer maxItemsInObjectGraph="2147483646" />
                <serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
                <!-- need to update in build script -->
                <serviceDebug includeExceptionDetailInFaults="true" />
                <secureMetadata locationUrl="http://localservices.mycompany.com/" />
                <exceptionHandler />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>

客户端生成的代码

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.18033")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(AnonymousType=true, Namespace="http://services.mycompany.com/Data/")]
public partial class FileStreamResponse : object, System.ComponentModel.INotifyPropertyChanged {

    private byte[] fileByteStreamField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(DataType="base64Binary", Order=0)]
    public byte[] FileByteStream {
        get {
            return this.fileByteStreamField;
        }
        set {
            this.fileByteStreamField = value;
            this.RaisePropertyChanged("FileByteStream");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName) {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null)) {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(IsWrapped=false)]
public partial class FileStreamResponse1 {

    [System.ServiceModel.MessageHeaderAttribute(Namespace="http://services.mycompany.com/Data/")]
    [System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
    public string FileName;

    [System.ServiceModel.MessageHeaderAttribute(Namespace="http://services.mycompany.com/Data/")]
    public bool IsZip;

    [System.ServiceModel.MessageHeaderAttribute(Namespace="http://services.mycompany.com/Data/")]
    public long Length;

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://services.mycompany.com/Data/", Order=0)]
    public ServiceTest.MyCompanyServices.FileStreamResponse FileStreamResponse;

    public FileStreamResponse1() {
    }

    public FileStreamResponse1(string FileName, bool IsZip, long Length, ServiceTest.MyCompanyServices.FileStreamResponse FileStreamResponse) {
        this.FileName = FileName;
        this.IsZip = IsZip;
        this.Length = Length;
        this.FileStreamResponse = FileStreamResponse;
    }
}

[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Advanced)]
[System.ServiceModel.MessageContractAttribute(WrapperName="GetFileStream2Response", WrapperNamespace="http://services.mycompany.com/Data/", IsWrapped=true)]
public partial class GetFileStream2Response {

    [System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://services.mycompany.com/Data/", Order=0)]
    public System.IO.Stream GetFileStream2Result;

    public GetFileStream2Response() {
    }

    public GetFileStream2Response(System.IO.Stream GetFileStream2Result) {
        this.GetFileStream2Result = GetFileStream2Result;
    }
}

客户端测试代码

class Program {
    static void Main( string[ ] args ) {
        var svc = new FileServiceClient( );
        Console.WriteLine( "Logging in..." );
        var ticket = svc.Logon( "userid", "password" );
        Console.WriteLine( "Calling service..." );
        FileStreamResponse fsr;
        bool isZip;
        long size;
        string filename = svc.GetFileStream( ticket, 51575, out isZip, out size, out fsr );
        if( fsr != null && fsr.FileByteStream != null ) { // fsr.FileByteStream is byte[]
            Console.WriteLine( "Filename: {0}", filename );
            Console.WriteLine( "Zip: {0}", isZip );
            Console.WriteLine( "Length: {0}", size );
            Console.WriteLine( "Saving file..." );
            using( var fs = new FileStream( Path.Combine( @"c:\temp", filename ), FileMode.OpenOrCreate, FileAccess.Write ) ) {
                const int bufferSize = 65536;
                var buffer = new byte[ bufferSize ];
                //var bytesRead = response.FileStreamResponse.FileByteStream.
            }
        }
        Console.WriteLine( "Press ENTER to exit." );
        Console.ReadLine( );
    }
}
4

1 回答 1

1

显然,这是问题所在(不是上面代码的一部分,而是传递给 GetFileStream 方法的类):

[MessageContract(IsWrapped = false)]
public class FileIDMessage : SecureMessageBase
{
    [MessageBodyMember]
    public int FileID;
}

如果我删除(IsWrapped = false),它将返回一个流而不是字节数组。

于 2013-03-13T15:39:57.093 回答