Бинарная сериализация HTTP посредством ASP.NET без использования WCF
При разработке приложения типа клиент/сервер вам зачастую может понадобиться послать объект вашему клиенту. Наиболее легким путем для программиста при работе с объектом является получение всего объекта с сервера, а не только некоторых свойств.
Одним из способов выполнения этого является использование 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-компрессии и внедрения в ваш код.
Сериализация объекта, на первый взгляд, придает больше контроля над тем, как все выполняется, причем не усложняя сам процесс.