Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

в 15:52, , рубрики: .net, azure, blob, microsoft, mobile services, Windows 8, windows azure, WinRT, метки: , , , , ,

Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

Добрый день.

Мы живем в мире тотальной глобализации как в реальной жизни, так и в виртуальной. Я имею в виду, что нам хочется иметь одни и те же данные, одни и те же настройки и одно и то же поведение программ на разных устройствах. Такой синхронизации всего и вся в наше время легко добиться с помощью облаков. Об этом и пойдет речь в данной статье, а именно о скрещивании приложения для Windows 8 (WinRT) с облаком Windows Azure для хранения данных и метаданных.

Вводная

Итак, предположим, что у нас есть приложение для Windows 8 (пусть это будет сервис хранения неких текстовых записей), которое:
1) Должно отображать список записей с минимальной информацией о каждой из них (допустим, заголовок или дату создания). Назовем это метаданными.
2) Должно иметь возможность показать подробную информацию о записи (контент) при переходе к конкретному элементу. Назовем это данными.
3) Должно синхронизировать данные между различными устройствами под управлением Windows 8 (создал запись дома, просмотрел ее же на работе).

Наиболее правильный подход, который я вижу, это разбить данные и метаданные и хранить их в разных местах. Это позволит нам быстро получить небольшие по объему метаданные для отображения в виде списке, и подгружать «тяжелые» данные по запросу пользователя.

По ходу этой статьи мы познакомимся с Windows Azure Mobile Services для хранения метаданных и Windows Azure Blob Storage для хранения данных. Впереди много текста и картинки.

Шаг 1. Работа с облачным хранилищем

Для более гибкой и кроссплатформенной работы с Windows Azure Blob Storage я дополнительно рекомендую ввести еще один слой в виде WCF-сервиса, который будет получать и обрабатывать запросы от мобильных клиентов. Поэтому первый шаг данного руководства будет состоять из нескольких этапов.

Создание нужных нам сервисов Windows Azure

Для начала нам необходимо подготовить облачное окружение, создав в Windows Azure две службы — Cloud Service и Storage. Начнем со второго. Заходим в портал управления Windows Azure. Внизу страницы есть большая кнопка с плюсом. По нажатии откроется выбор сервисов для создания. Нам нужен DATA SERVICES -> STORAGE:
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

Вводим любое удобное для нас имя нового сервиса, нажимаем кнопку-галку внизу и ждем, пока сервис не получит статус Online. После этого заходим в настройки нашего хранилища и ищем глазами и мышкой кнопку «Mange keys» с иконкой буквы i на борту. Нажимаем на нее и видим перед собой три поля. В первом будет находиться имя данного сервиса, который мы ему присвоили при создании, а во втором и третьем будут храниться ключи доступа. Запомним первый из них, он нам пригодится уже скоро.

Создание WCF сервиса

Для создания WCF сервиса и соотвествующей ему службы в Windows Azure мы воспользуемся Visual Studio 2012. Я буду показывать на примере версии Ultimate, но для бесплатного использования подойдет версия Web.
Итак, открываем студию и создаем новый проект с типом Cloud:
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

В появившемся окне нам будет предложено выбрать типы проектов, которые надо разместить в облаке. Нас интересует WCF Service Web Role. Выбираем его и добавляем к списку создаваемых (не забываем переименовать):
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

Visual Studio, после недолгих раздумий, создаст для нас два проекта, один из которых будет проектом WCF службы, а второй — специальный проект для публикации в облако Windows Azure. Давайте немного их понастраиваем.

Чтобы безболезненно публиковать наш сервис в облако, Visual Studio должна знать, в какое именно облако ей это делать, а также понимать, что мы имеем на это право. Чтобы ее убедить, достаточно нажать правой кнопкой мыши на проекте Cloud и выбрать пункт меню Publish:
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

Если вы ранее не публиковали ничего в облако, то вместо значения WindowsAzureMSDN у вас будет пусто. Чтобы было густо, достаточно перейти по ссылке, скачать профиль публикаций и испортировать его с помощью кнопки Import в Visual Studio. Это позволит вам выполнять операции над облачными сервисами прямо из IDE.

После того, как у нас появился доступ к облаку из VS2012, переходим на следующий шаг, где создадим непосредственно Cloud Service для хостинга нашей WCF-службы. На вкладке Common Settings выбираем Cloud Service -> Create New, а на вкладке Advanced Settings указываем существующий Storage Account (он должен уже быть доступным для выбора в списке). Старайтесь, чтобы и Cloud Service и Storage Account были в одной зоне:
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

После выполнения этих действий нам достаточно просто нажать кнопку Publish, и проект утечет в сеть.

Шаг 2. Использование хранилища

Первым делом надо добавить строку соединения в файл web.config нашего сервиса. Строка выглядит следующим образом:
DefaultEndpointsProtocol=https;AccountName=имя_сервиса;AccountKey=тот_самый_ключ_от_Storage

Работа с облачным хранилищем может осущетсвляться двумя способами — с помощью REST API и с помощью .NET обертки. В данной статье я буду использовать второй вариант как наиболее простой. Тем более не зря же мы создавали свой собственный сервис.

Итак, для того, чтобы пользоваться данным функционалом, надо подключить к своему проекту NuGet пакет «Windows Azure Storage»:
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

Подключение и управление BLOB-контейнерами происходит с помощью клиента:

using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;

CloudStorageAccount storageAccount = CloudStorageAccount.Parse(_connectionString);
_blobClient = storageAccount.CreateCloudBlobClient();

Дальнейшая работа с хранилищем довольно проста:

// Получение контейнера
CloudBlobContainer container = BlobClient.GetContainerReference(ContainerName);
// Создание, если его не существует
container.CreateIfNotExists();
// Получение блока по принципу "префикс-<id записи>"
CloudBlockBlob blockBlob = container.GetBlockBlobReference(BlobNamePrefix + data.Id);

// Сериализуем данные
var serializer = new XmlSerializer(typeof(CompositeType));
using (var s = new MemoryStream())
{
    serializer.Serialize(s, data);
    s.Seek(0, SeekOrigin.Begin);

    // И пишем в blob
    blockBlob.UploadFromStream(s);
}

Аналогично данные можно получить:

// Получение контейнера
CloudBlobContainer container = BlobClient.GetContainerReference(ContainerName);
// Если не существует - возвращаем null
if (!container.Exists())
    return null;

// Так же пытаемся получить блок
var blockBlob = container.GetBlockBlobReference(BlobNamePrefix + id);
if (!blockBlob.Exists())
    return null;

// И десериализуем бинарные данные
var serializer = new XmlSerializer(typeof(CompositeType));
CompositeType result = null;

using (var s = new MemoryStream())
{
    // Скачиваем данные из блоба
    blockBlob.DownloadToStream(s);
    s.Seek(0, SeekOrigin.Begin);
    result = serializer.Deserialize(s) as CompositeType;
}

return result;

Вышеописанные методы были помещены в класс обертку, а сам WCF-сервис обаладает простым контрактом из двух действий:

[ServiceContract]
public interface IBlobService
{
    [OperationContract]
    CompositeType GetData(int value);

    [OperationContract]
    void PutData(CompositeType data);
}

!!! Тут надо упомянуть важную, но абсолютно неочевидную вещь. Имена блоб контейнеров и блоков должны быть в маленьком регистре. То есть имя BlobContainer вызовет ошибку при попытке создания, а, например, blob-container создастся без проблем.

После того, как мы написали сервис, еще раз публикуем его в облако и после завершения этой процедуры он будет доступен по адресу ваше_имя_сервиса.cloudapp.net/BlobService.svc.

Шаг 3. Мобильные сервисы

Предыдущие два шага были направлены на создание инфраструктуры для хранения «данных» — информации большого объема, которая нужна не всегда, а по запросу. Теперь давайте перейдем к хранению «метаданных». Для этого мы воспользуемся недавней новинкой в Windows Azure — Mobile Services.

Создать новый мобильный сервис так же просто, как и остальные услуги в Windows Azure. Опять идем на портал управления, где внизу в меню создания выбираем COMPUTE -> MOBILE SERVICE и видим перед собой мастер:
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

Указываем в нем имя будущего сервиса, регион размещения (не забываем размещаться где-то в одном месте), указываем Storage, где будут храниться наши данные (можно использовать уже существующий или создать новый) и завершаем мастер.

Как только сервис будет создан, переходим на его страницу в раздел, помеченный иконкой облака с молнией (названия у него я не знаю). На этой странице есть две опции — Create a new Windows Store app и Connect an existing Windows Store app. Первая позволит вам скачать архив с приложением, настроенным для работы с вашим мобильным сервисом, а вторая просто даст кусочек кода, который надо внедрить в существующее приложение. В принципе сейчас не важно, какую опцию вы выберете. Я предлагаю использовать вторую и создать приложение вручную.

А пока мы этого не сделали, давайте подготовим Mobile Services к использованию. Для этого сперва пеерйдем в раздел Data (в верхнем меню) и добавим новую таблицу для хранения записей. Назвать можно как угодно, у меня — TestItem:
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

В этой таблице впоследствии будут размещаться записи метаданных, введенные в приложении для Windows 8.

Шаг 4. Windows 8

Настало время сделать то, ради чего все затевалось. Приложение для Windows 8 (WinRT) можно бесплатно создать в Express версии Visual Studio 2012 (наподобие той, что мы использовали для WCF сервиса, но теперь для Win8 приложений).
File -> New Project -> Windows Store:
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

Сперва надо добавить необходимые ссылки на библиотеки, чтобы можно было пользоваться благами Mobile Services. Если вы обратили внимание, то на предыдущем шаге Windows Azure предалал нам скачать и установить Mobile Services SDK. Это нужно сделать, ибо с его помощью мы будем работать с облачными сервисами для мобильных устройств.

Как только SDK установлен, мы можем подключить его к проекту с помощью стандартной процедуры Add Reference:
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

Затем подключим еще и ссылку на наш WCF сервис. Делается это также несложно с помощью стандартного диалога Add Service Reference:
Мобильные сервисы, блобы и Windows 8. Храним данные в облаке

В результате подключения Service Reference Visual Studio создаст для нас специальный класс обертку, который будет выглядеть как обычный класс с контрактом сервиса, но на самом деле будет обращаться к удаленному WCF по указанному адресу.

Ну и в завершение, добавим код для использования мобильных сервисов, который, как я говорил выше, можно получить на странице с облачком и молнией в Windows Azure. Выглядит он примерно так:

public static MobileServiceClient MobileService = new MobileServiceClient(
            "https://***.azure-mobile.net/",
            "secret_key");

Это поле я добавил на страницу App.xaml, чтобы иметь доступ к мобильным сервисам из любого места в приложении.

Шаг 5. Собираем все вместе

Настало время соединить все пути в одной точке и написать код, который при добавлении новой записи будет размещать ее в хранилище Azure Blob Storage и Mobile Services.

private async Task PutDataTestWCF(CompositeType data)
{
    // Получаем клиент для работы с WCF
    var cli =
        await
        Task.Run(() => new BlobServiceClient(new BasicHttpBinding(), new EndpointAddress(CloudServiceEndpoint)));
    // Вызываем сгенеренный метод добавления данных (асинхронный)
    await cli.PutDataAsync(data);
    // Не забываем закрыть клиент
    await cli.CloseAsync();

    // Получаем таблицу в мобильных сервисах
    var table = App.MobileService.GetTable<TestItem>();
    // Выбираем из нее записи
    var list = await table.Select(x => x.Id == data.Id).ToListAsync();

    // Если такая запись есть, то делаем обновление, иначе - вставку
    if (list != null && list.Count > 0)
        await table.UpdateAsync(new TestItem() {Id = data.Id, Text = data.Text});
    else
        await table.InsertAsync(new TestItem() {Text = data.Text});
}

Тут стоит обратить внимание на несколько вещей. Во первых, все методы, которые так или иначе работают с сетью, являются асинхронными. Даже класс клиента к WCF сервису, который сгенерировался автоматически, тоже содержит асинхронные методы (PutDataAsync). Это здорово, поскольку позволяет делать приложение более отзывчивым, не заставляя пользователя наблюдать заблокированный интерфейс, пока приложение пытается соединиться с Интернетом.
Помимо этого, работа с обоими сервисами стала довольно простой и прозрачной. Что работа с WCF, что с Mobile Services, обе они выглядят как простые вызовы .Net кода, скрывая все детали «где-то там». Я не писал здесь никаких абстрактных слоев доступа к данным, но если заморочиться и сделать все грамотно, то мы сможем легко делать заглушки и моки (mock) для тестирования приложения.

Заключение

В этой статье в первую очередь я хотел показать не как писать Windows 8 приложения, а как встроить в них возможность работы с различными типами облачного хранилища разлиными способами. Я сознательно привел не так много кода, поскольку статья и так получилась большой и, возможно, сложной для восприятия. Ниже я прилагаю архив с кодом, который можно использовать для тренировки:
Скачать архив
В нем я заменил все упоминания своего сервиса на *** или ****. Думаю будет понятно, что и куда надо подставить, чтобы все взлетело.

При подготовке статьи и тестового приложения были использованы следующие материалы:
Официальное руководство по работе с Blob Storage
Официальное руководство по работе с данными в мобильных сервисах
Google, Bing, Yandex
— Собственные мысли и догадки

P.S. Большая просьба к неравнодушным минусаторам — пишите, пожалуйста, аргументацию своих минусов или в комментах, или в личку. Мне важно знать свои огрехи, чтобы исправлять их в будущих публикациях. Спасибо большое.

Автор: glamcoder

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js