Бинарная сериализация HTTP посредством ASP.NET без использования WCF

Источник: cyberguru

При разработке приложения типа клиент/сервер вам зачастую может понадобиться послать объект вашему клиенту. Наиболее легким путем для программиста при работе с объектом является получение всего объекта с сервера, а не только некоторых свойств. Одним из способов выполнения этого является использование WCF или Веб-сервисов, что предоставляет вам большой набор инструментов, таких как сериализация. Однако эти наборы технологий зачастую привносят немало перерасходов и сложностей в ваш проект, чего вам наверняка не хотелось бы видеть в случаях, когда вам необходимо просто переслать и получить один или более объектов.

При такой дилемме стоило потратить некоторое время на поиск решения. Нашей целью было нахождение простого и ясного метода создания объекта на сервере, его сериализация и отсылка обратно к клиенту. Безопасность и функциональная совместимость не входили в список задач, но они могут быть реализованы позже. Ограничением было то, что нам необходимо было быстрое решение, и оно должно было работать посредством стандартного HTTP-протокола.

Решение заключается в создании ASP.NET-страницы, которая считывает строку запроса для определения того, какой объект необходимо вернуть, создает его, сериализует его в двоичный формат и возвращает в виде двоичного приложения к клиенту. Клиент загружает файл при помощи класса WebClient() и преобразовывает его из последовательной формы в объект.

Как клиент, так и сервер используют библиотеку классов, содержащую общий объект. Поначалу мы реализовали это при помощи XML-сериализации, но она оказалась довольно медленной, но тем не менее вы можете ее использовать при необходимой функциональной совместимости.

Пояснения

Вам стоит помнить о том, что это не единственный способ - вы наверняка можете выполнить это при помощи WCF, используя специализированную привязку или MTOM, но нам кажется, что данные методы чересчур вовлечены и привносят ненужную сложность в простые проекты.

Использование кода

При загрузке страницы веб-сервера мы включаем следующий код для проверки того, какой объект требует клиент, и возвращаем объект, преобразованный в двоичное приложение.
protected void Page_Load(object sender, EventArgs e)
{
    // Проверка того, какой объект необходим клиенту
    if (Request.QueryString["op"] == "getdata")
    {
        // Создание нового экземпляра объекта с выборочными данными
        var data = new SampleData();
        data.moreData = 34343;
        data.otherData = true;
        data.SomeData = "fewoifjweofjwepo";
        // Установка типа содержимого и заголовка
        // байтовый поток позволяет нам посылать данные бинарного типа
        // название файла здесь не относится к делу так как на самом деле
        // он не используется клиентом
        Response.ContentType = "application/octet-stream";
        Response.AppendHeader("Content-Disposition",
                             "attachment; filename=sampleData.bin");
        // Сериализация объекта и запись его в ответный поток
        var binaryFormatter = new BinaryFormatter();
        binaryFormatter.Serialize(Response.OutputStream, data);
        // Важно завершить ответ, иначе клиенту будут посланы другие данные страницы  
            Response.End();
    }
Со стороны клиента мы создали запрос к серверу используя строку запроса и преобразовали ответ.
// Создание ссылки для сервиса, она может быть сохранена в файле конфигурации
string url = "http://localhost/BinaryServiceSample/Default.aspx?op=getdata";
// Закрузка данных в битовый массив
// Эти данные содержат реальный объект
var client = new WebClient();
byte[] result = client.DownloadData(url);
// Создание потока данных для хранения объекта
var mem = new MemoryStream(result);
var binaryFormatter = new BinaryFormatter();
var data = (SampleData)binaryFormatter.Deserialize(mem);
mem.Close();
// Запись объекта в консоль
Console.Write(data.ToString());
Console.ReadLine();

Интересные факты

  • Хотя двоичная сериализация может показаться более удобной, она может не быть совместимой с различными платформами.
  • Сериализация объектов при помощи двоичной сериализации значительно быстрее, чем XML.
  • Данный код не включает в себя проверку на ошибки, но это с легкостью можно внедрить. Мы не включили ее для простоты и удобства в изучении.
  • Одним из способов добавить немного безопасности является шифрование битов и отсылка их клиенту. Это, конечно, сделает функциональную совместимость более сложной задачей.
  • Дополнительная скорость в передаче данных может быть достигнута при помощи компрессии битов до их отсылки - ICSharpCode.SharpZipLib.dll может сжать биты памяти и при этом оно бесплатно, но вы также можете выполнить это при помощи .NET Framework путем реализации HTTP-компрессии и внедрения в ваш код.
  • Сериализация объекта, на первый  взгляд, придает больше контроля над тем, как все выполняется, причем не усложняя сам процесс.

Страница сайта http://test.interface.ru
Оригинал находится по адресу http://test.interface.ru/home.asp?artId=23571