如何在 WCF 中使用 HTTP 发送 System.IO.Stream 转换为对象?

发布于 2024-10-27 17:42:21 字数 5770 浏览 4 评论 0原文

我有一个非常简单的 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();
        }
    }
}

<代码>}

客户端程序:

命名空间客户端 { [ServiceContract(命名空间 = "http://My.WCF.Samples")] 公共接口IService1 { 【运营合同】 流 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;
    }
}

<代码>}

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

公共对象 GetString() { 字符串 str = "ABC";

        Stream ms = new MemoryStream();

        SerializeData<string>(str, ms);

        return (object)ms;

}

但是,当我这样做时,在 Button1_Click 事件内,在 ***memStr = proxy.GetString();*** 行,我得到一个通信异常。我在日语操作系统中工作,所以我收到的异常消息是日语的,所以我会尽力翻译成英语。如果不是很清楚,请原谅我。

***Error occured in the reception of HTTP response concerning [url]http://localhost:8000/WCFSampleService/HelloWCF[/url]. Cause of the error could be Service End Point binding is not using an HTTP protocol. Or as a different cause, it is also possible that HTTP request context is suspended according to the server (as in the case of server being shut down). Please refer the server log for more details.***

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

提前致谢!

I have a very simple WCF program where I have a simple self-host and a client running on the same computer. There is a single method which returns a System.IO.Stream, which is actually a serialized form of a simple string. (This could be any number of data types, but for the time being let's take it as a string).

Following is the code I use if you want to take a look at. SerializeData() and DeserializeData() are methods used to do just that, and works fine.

Host Service:

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();
        }
    }
}

}

Client Program:


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

}

Now, this works fine. It serializes a string into a Stream and sends using HTTP quite fine. However, I have a need to convert of cast this Stream into an object before sending. Simply put, I need the GetString() method to look like this:


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

        Stream ms = new MemoryStream();

        SerializeData<string>(str, ms);

        return (object)ms;

}

However, when I do this, inside the Button1_Click event, at the line ***memStr = proxy.GetString();*** I get a CommunicationException. I work in a Japanese OS, so the exception message I get is in Japanese so I'll try to translate into English as best as I can. Forgive me if it is not very clear.

***Error occured in the reception of HTTP response concerning [url]http://localhost:8000/WCFSampleService/HelloWCF[/url]. Cause of the error could be Service End Point binding is not using an HTTP protocol. Or as a different cause, it is also possible that HTTP request context is suspended according to the server (as in the case of server being shut down). Please refer the server log for more details.***

What exactly is the problem and how can I get the program to work the way I want? It says to look at the log files but where can I find them?

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

迎风吟唱 2024-11-03 17:42:21

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

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

Would you not be better off just returning the string? Surely the string returned as a stream over an Http binding will be being Base64 encoded, which normally doubles the size of the data being returned!

Maybe you could consider TcpBinding as an alternative.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文