如何使用WCF中的HTTP发送System.IO.Stream到对象?

时间:2011-03-29 06:00:17

标签: c# wcf object stream wcf-binding

我有一个非常简单的WCF程序,我有一个简单的自主机和在同一台计算机上运行的客户端。有一个方法可以返回System.IO.Stream,它实际上是一个简单字符串的序列化形式。 (这可以是任意数量的数据类型,但暂时让我们将其作为字符串)。

以下是我想要查看的代码。 SerializeData()和DeserializeData()是用来做到这一点的方法,并且工作正常。

主机服务:

namespace HelloWCF1
{
    [ServiceContract(Namespace = "http://My.WCF.Samples")]
    public interface IService1
    {
        [OperationContract]
        Stream GetString();
    }

public class Service1 : IService1
{
    //Simple String
    public Stream GetString()
    {
        string str = "ABC";

        Stream ms = new MemoryStream();
        SerializeData<string>(str, ms);

        return ms;
    }

    /// <summary>
    /// Serialize an object of the type T to a Stream
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="objectToSerialize"></param>
    /// <param name="str"></param>
    public void SerializeData<T>(T objectToSerialize, Stream str)
    {
        BinaryFormatter bf = new BinaryFormatter();

        try
        {
            bf.Serialize(str, objectToSerialize);
            str.Position = 0;
        }
        catch (Exception)
        {
        }
    }

    /// <summary>
    /// Deserialize a Stream
    /// </summary>
    /// <param name="dataToDeserialize"></param>
    /// <returns></returns>
    public object DeserializeData(Stream dataToDeserialize)
    {
        BinaryFormatter bf = new BinaryFormatter();
        object ret = null;

        try
        {
            ret = bf.Deserialize(dataToDeserialize);
        }
        catch (Exception)
        {
        }

        return ret;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Uri baseAddr = new Uri("http://localhost:8000/WCFSampleService");

        //ServiceHost is created by defining Service Type and Base Address
        using (ServiceHost svcHost = new ServiceHost(typeof(Service1), baseAddr))
        {

            //Trace message for service start
            Console.WriteLine("Service Starting...");

            //Adding an end point
            svcHost.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "HelloWCF");

            //Open service host
            svcHost.Open();

            Console.WriteLine("Press [Enter] to terminate.");
            Console.ReadLine();

            //Close service host
            svcHost.Close();
        }
    }
}

namespace HelloWCF1 { [ServiceContract(Namespace = "http://My.WCF.Samples")] public interface IService1 { [OperationContract] Stream GetString(); } public class Service1 : IService1 { //Simple String public Stream GetString() { string str = "ABC"; Stream ms = new MemoryStream(); SerializeData<string>(str, ms); return ms; } /// <summary> /// Serialize an object of the type T to a Stream /// </summary> /// <typeparam name="T"></typeparam> /// <param name="objectToSerialize"></param> /// <param name="str"></param> public void SerializeData<T>(T objectToSerialize, Stream str) { BinaryFormatter bf = new BinaryFormatter(); try { bf.Serialize(str, objectToSerialize); str.Position = 0; } catch (Exception) { } } /// <summary> /// Deserialize a Stream /// </summary> /// <param name="dataToDeserialize"></param> /// <returns></returns> public object DeserializeData(Stream dataToDeserialize) { BinaryFormatter bf = new BinaryFormatter(); object ret = null; try { ret = bf.Deserialize(dataToDeserialize); } catch (Exception) { } return ret; } } class Program { static void Main(string[] args) { Uri baseAddr = new Uri("http://localhost:8000/WCFSampleService"); //ServiceHost is created by defining Service Type and Base Address using (ServiceHost svcHost = new ServiceHost(typeof(Service1), baseAddr)) { //Trace message for service start Console.WriteLine("Service Starting..."); //Adding an end point svcHost.AddServiceEndpoint(typeof(IService1), new BasicHttpBinding(), "HelloWCF"); //Open service host svcHost.Open(); Console.WriteLine("Press [Enter] to terminate."); Console.ReadLine(); //Close service host svcHost.Close(); } } }

客户计划:

}

namespace Client { [ServiceContract(Namespace = "http://My.WCF.Samples")] public interface IService1 { [OperationContract] Stream GetString(); }

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private IService1 proxy = null;
    private Stream memStr = new MemoryStream();

    private void button1_Click(object sender, EventArgs e)
    {
        //Create end point
        EndpointAddress epAddr = new EndpointAddress("http://localhost:8000/WCFSampleService/HelloWCF");

        //Create proxy
        proxy = ChannelFactory<IService1>.CreateChannel(new BasicHttpBinding(), epAddr);

        //WCF Service Method is called to aquire the stream
        try
        {
            memStr = proxy.GetString();
            string str = (string)DeserializeData(memStr);
            MessageBox.Show(str);
        }
        catch (CommunicationException commEx)
        {
            MessageBox.Show("Service Call Failed:" + commEx.Message);
        }
    }       

    /// <summary>
    /// Serialize an object of the type T to a Stream
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="objectToSerialize"></param>
    /// <param name="str"></param>
    public static void SerializeData<T>(T objectToSerialize, Stream str)
    {
        BinaryFormatter bf = new BinaryFormatter();

        try
        {
            bf.Serialize(str, objectToSerialize);
            str.Position = 0;
        }
        catch (Exception)
        {
        }
    }

    /// <summary>
    /// Deserialize a Stream
    /// </summary>
    /// <param name="dataToDeserialize"></param>
    /// <returns></returns>
    public static object DeserializeData(Stream dataToDeserialize)
    {
        BinaryFormatter bf = new BinaryFormatter();
        object ret = null;

        try
        {
            ret = bf.Deserialize(dataToDeserialize);
        }
        catch (Exception)
        {
        }

        return ret;
    }
}

现在,这很好用。它将字符串序列化为流并使用HTTP发送非常好。但是,我需要在发送之前将此Stream转换为对象。简单地说,我需要GetString()方法如下所示:

public partial class Form1 : Form { public Form1() { InitializeComponent(); } private IService1 proxy = null; private Stream memStr = new MemoryStream(); private void button1_Click(object sender, EventArgs e) { //Create end point EndpointAddress epAddr = new EndpointAddress("http://localhost:8000/WCFSampleService/HelloWCF"); //Create proxy proxy = ChannelFactory<IService1>.CreateChannel(new BasicHttpBinding(), epAddr); //WCF Service Method is called to aquire the stream try { memStr = proxy.GetString(); string str = (string)DeserializeData(memStr); MessageBox.Show(str); } catch (CommunicationException commEx) { MessageBox.Show("Service Call Failed:" + commEx.Message); } } /// <summary> /// Serialize an object of the type T to a Stream /// </summary> /// <typeparam name="T"></typeparam> /// <param name="objectToSerialize"></param> /// <param name="str"></param> public static void SerializeData<T>(T objectToSerialize, Stream str) { BinaryFormatter bf = new BinaryFormatter(); try { bf.Serialize(str, objectToSerialize); str.Position = 0; } catch (Exception) { } } /// <summary> /// Deserialize a Stream /// </summary> /// <param name="dataToDeserialize"></param> /// <returns></returns> public static object DeserializeData(Stream dataToDeserialize) { BinaryFormatter bf = new BinaryFormatter(); object ret = null; try { ret = bf.Deserialize(dataToDeserialize); } catch (Exception) { } return ret; } }

}

public object GetString() { string str = "ABC";

然而,当我这样做时,在

        Stream ms = new MemoryStream();

        SerializeData<string>(str, ms);

        return (object)ms;
事件内,在 Stream ms = new MemoryStream(); SerializeData<string>(str, ms); return (object)ms; 行,我得到一个CommunicationException。我在日语操作系统中工作,所以我得到的异常消息是日语,所以我会尝试尽可能地翻译成英语。如果不是很清楚,请原谅我。

}

究竟是什么问题,如何让程序以我想要的方式运行?它说要查看日志文件但我在哪里可以找到它们?

提前致谢!

1 个答案:

答案 0 :(得分:0)

你回来的字符串会不会更好?当然,作为Http绑定上的流返回的字符串将被Base64编码,这通常会使返回的数据的大小加倍!

也许您可以考虑将TcpBinding作为替代方案。