65.9K
CodeProject 正在变化。 阅读更多。
Home

无需 WCF 通过 ASP.NET 实现 HTTP 二进制序列化

starIconstarIconstarIconstarIconstarIcon

5.00/5 (10投票s)

2009年8月12日

CPOL

3分钟阅读

viewsIcon

59305

downloadIcon

369

展示了如何在不使用 WCF 的情况下使用二进制序列化来序列化对象。

引言

在开发客户端/服务器应用程序时,您经常需要将对象发送到客户端。对于我们程序员来说,最简单的方法是从服务器获取整个对象,而不仅仅是一些属性。

一种方法是使用 WCF 或 Web Services,它们为您提供了一整套工具,例如序列化,来完成这项任务,但是这些技术通常会给您的项目带来很多开销和复杂性,如果您只是发送和接收一个或多个对象,您通常不希望这样。

面对这个困境,我花了一些时间寻找解决方案。我的目标是找到一种非常简单、简洁的方式,在服务器上创建一个对象,将其序列化,然后发送回客户端。此时,安全性和互操作性不是问题,但可以在以后实现。 对此的约束是它必须很快,并且必须通过基本的 HTTP 协议工作。

我的解决方案是创建一个 ASP.NET 页面,该页面读取查询字符串以确定要返回的对象,创建该对象,将其序列化为二进制,然后将其作为二进制附件返回给客户端。 客户端使用 WebClient() 类下载此文件,并将其反序列化回对象。

服务器和客户端共享一个包含通用类的类库。 最初,我使用 XML 序列化实现了这一点,但发现它非常慢,但如果您需要互操作性,也可以使用它。

背景

请记住,这不是执行此操作的唯一方法。 您可以使用自定义绑定或使用 MTOM 通过 WCF 来执行此操作,但根据我的经验,我发现这些方法过于复杂,并且为简单的项目增加了不必要的复杂性。

Using the Code

在 Web 服务器页面加载时,我们包含代码以检查客户端请求的对象,并将序列化的对象作为二进制附件返回。

protected void Page_Load(object sender, EventArgs e)
{
    // Check which object the client wants
    if (Request.QueryString["op"] == "getdata")
    {
        // Create a new instance of the sample data object
        var data = new SampleData();
        data.moreData = 34343;
        data.otherData = true;
        data.SomeData = "fewoifjweofjwepo";
        // Set content type and header
        // octet-stream allow us to send binary data
        // the file name here is irrelevant as it is 
        // not actually used by the client.
        Response.ContentType = "application/octet-stream";
        Response.AppendHeader("Content-Disposition", 
                             "attachment; filename=sampleData.bin");
        // Serialzie the object and write it to the response stream
        var binaryFormatter = new BinaryFormatter();
        binaryFormatter.Serialize(Response.OutputStream, data);
        // Its important to end the response, overwise the other page content
        // would be sent to the client.
        Response.End();
    }

在客户端,我们使用查询字符串创建对服务器的请求,并反序列化响应。

// Create the url for the service, this could be stored in a configuration file
string url = "https:///BinaryServiceSample/Default.aspx?op=getdata";
// Download the data to a byte array
// This data contains the actual object
var client = new WebClient();
byte[] result = client.DownloadData(url);
// Create a memory stream to stored the object
var mem = new MemoryStream(result);
var binaryFormatter = new BinaryFormatter();
var data = (SampleData)binaryFormatter.Deserialize(mem);
mem.Close();
// Write object to the console
Console.Write(data.ToString());
Console.ReadLine();

关注点

  • 尽管二进制序列化可能“感觉”更舒服,但它可能不跨不同平台兼容。
  • 使用二进制序列化序列化对象比 XML **快得多**。
  • 此代码不包含任何错误处理,这可以很容易地集成到其中。 我没有包括它,以使其更加清晰和简单。
  • 添加安全性的一种方法是在将实际字节发送到客户端之前对其进行加密。 当然,这将使互操作性非常困难。
  • 可以通过在发送之前压缩字节来获得额外的传输速度。 我知道ICSharpCode.SharpZipLib.dll可以在内存中压缩字节,它是免费的,但是您也可以通过实施 HTTP 压缩并将其嵌入到您的代码中来使用 .NET Framework - 请查看本文以获取示例: https://codeproject.org.cn/Articles/38067/Compress-Response.aspx
  • 像这样序列化对象似乎让我可以更好地控制事物的完成方式,而又不会增加太多的复杂性。

我想收到关于此的评论、建议和建设性的批评,如果您有任何意见或改进,请告诉我,以便我可以将其包括在内。

感谢 Andre Sanches 对本文的贡献。

© . All rights reserved.