.
Сценарий
Предположим, некая компания использует список SharePoint (названный RFQ) для отслеживания запросов на цены, которые поступают от потенциальных потребителей через сайт компании, основанный на SharePoint 2010. Список интегрирован с рядом бизнес-процессов, которые облегчают процесс ответа на RFQ. Бизнес–процесс включает в себя составление сметы для RFQ, создание формального рабочего задания statement of work (SOW), состоящего из сметы, одобрения SOW и предоставления SOW потенциальному потребителю. Сотрудники компании используют приложения Windows 8 для отслеживания RFQ и создания смет для них. Как только завершается процесс ответа на RFQ, список SharePoint обновляется, и сотрудники получают уведомления на свои компьютеры и планшеты Windows 8. Уведомления информируют их о статусе процесса для каждого RFQ и любого этапа действий, который сотрудник должен выполнить.
В частности, в статье будет показано, как отсылать уведомления в приложение Windows 8, когда потенциальному покупателю предоставляется новый RFQ, и как обновлять список RFQ, когда создается смета для RFQ с помощью приложения Windows 8.
Компоненты
Необходимая архитектура для создания бизнес–процесса извещающего уведомления в приложении сайта SharePoint 2010, состоит из четырех компонентов.
- Сервер SharePoint 2010 – проверяет изменения элементов списка и передает их службе, как это делает приложение ASP.NET MVC 4.
- Приложение ASP.NET MVC 4 – получает события от SharePoint, упаковывает их и отсылает службам Windows Push Notification Services.
- Службы Windows Push Notification Services (WNS) – получают запросы об уведомлениях и направляют уведомления подписчикам.
- Приложение Windows 8 – показывает уведомления, полученные от WNS.
На рисунке 1 показаны компоненты, составляющие решение. Прямоугольник Windows 8 слева обозначает компьютер с работающей на нем Windows 8. Встроенная платформа уведомлений Notification Client Platform операционной системы Windows 8 получает уведомления и отсылает их к приложениям Windows 8.
Рисунок 1. Архитектура решения для отправки уведомлений |
На сервере SharePoint приемник событий с элементами списка, который прикреплен к списку SharePoint RFQ, сработает тогда, когда какой-либо элемент в списке будет создан или обновлен. Приемник событий с элементами списка инициирует отсылку всплывающего уведомления и уведомления-«плитки» в приложение Windows 8, выполняя запрос в локальную или «облачную» службу, который, в свою очередь, вызывает Windows Push Notification Service (WNS). Затем WNS передает уведомления в приложение Windows 8.
Хотя этот пример использует приемник событий с элементами списка для инициирования передачи уведомлений, вы также можете задействовать запуск задания по расписанию или пользовательский код, вызываемый веб-частью или другим компонентом. Например, можно вызвать службу ASP.NET MVC 4 для отсылки уведомления из рабочего процесса.
Необходима промежуточная служба между приемником событий с элементами списка и WNS, потому что библиотеки WNS API подчиняются. NET 4 Framework. Таким образом, никакие сборки, развернутые на SharePoint, не могут ссылаться на эти библиотеки. Это означает, что на библиотеки WNS нельзя ссылаться и вызывать их напрямую из приемника событий с элементами списка.
Чтобы обойти это ограничение, я развернул службу ASP.NET MVC 4. Служба ASP.NET MVC 4 использует библиотеки WNS, поэтому она как раз подходит. Вы можете развернуть службу и на других технологиях, которые поддерживают библиотеки WNS (например, ASP.NET Web API). Служба ASP.NET MVC 4 (или любая другая) может быть размещена либо локально (в компании), либо в «облаке» – на ваш выбор.
Аутентификация
Помните, что в этом сценарии не только система Windows 8 получает уведомления, когда данные изменяются в SharePoint, но и сотрудники просматривают RFQ и создают сметы с использованием приложения Windows 8. Это означает, что приложение Windows 8 должно аутентифицироваться на сервере SharePoint, прежде чем оно сможет запросить список RFQ.
Приложение Windows 8 использует один из двух подходов к аутентификации на сервере SharePoint, в зависимости от того, как сотрудник зарегистрировался на компьютере Windows 8 и как он подсоединяется к сети, к которой относится сервер SharePoint 2010. Когда приложение Windows 8 работает на компьютере, на котором пользователь зарегистрировался с учетными данными домена и подсоединенного к сети домена, данные аутентификации передаются автоматически на сервер SharePoint. Когда приложение Windows 8 работает на компьютере, на котором пользователь не зарегистрирован с учетной записью домена и не подсоединен к сети домена, приложение Windows 8 выдает ему запрос на учетные данные. Для обеспечения этого варианта никакого специального кода не требуется. Приложение Windows 8 автоматически запрашивает учетные данные, когда это необходимо.
Уведомления
Теперь давайте вернемся к началу процесса, когда новый элемент списка добавляется к RFQ, и рассмотрим код для отсылки уведомлений. Во-первых, приемник событий с элементами списка создает один или несколько URL, чтобы вызвать службу ASP.NET MVC 4, которая, в свою очередь, вызовет WNS для передачи уведомлений. Эти URL содержат информацию, которая помогает службе ASP.NET MVC 4 определить тип отсылаемого уведомления и то, какие данные должны быть включены в него. В зависимости от того, какие изменения внесены в список RFQ, приемник событий с элементами списка создает один или несколько подходящих URL для передачи всплывающего уведомления или уведомления-«плитки» в приложение Windows 8. Например, когда добавляется новый элемент к списку RFQ, код в листингах 1, 2 и 3 выполняет метод ItemAdded для элемента списка в приемнике событий. Этот код создает одно всплывающее уведомление и три уведомления-«плитки».
Заметьте, что событие ItemUpdated в приемнике событий элементов списка следует тому же самому примеру для отсылки уведомлений. Однако мы не будем подробно останавливаться на этом в данной статье. Событие ItemUpdated оценивает столбец статуса в списке RFQ и отсылает уведомления об обновлении статуса RFQ сотрудникам. Событие ItemUpdated также отсылает обновленную информацию о продажах, когда покупатель принимает условия в SOW. Я подчеркиваю это для того, чтобы показать, что вы можете применять уведомления для нескольких типов событий, которые происходят со списками SharePoint.
Всплывающее уведомление. Первый тип уведомлений – это всплывающее уведомление (рисунок 2).
Рисунок 2. Пример всплывающего уведомления |
Уведомление оповещает сотрудника о начале задания (в данном случае – создании сметы). Всплывающие уведомления появляются на экране Windows 8 Start. В листинге 1 показан код, который генерирует URL для отсылки всплывающего уведомления через службу ASP.NET MVC 4.
Уведомление-«плитка». Второй тип уведомления – это уведомление-«плитка». На рисунке 3 показаны три таких уведомления. Посмотрите на первую «плитку», которая информирует сотрудников о том, что в системе есть новая задача. Код, который генерирует это уведомление-«плитку», показан в листинге 2.
Рисунок 3. Пример уведомлений-«плиток» |
Уведомления появляются на «плитке», соответствующей приложению Windows 8, которое их выводит на экране Windows 8 Start.
Центральное уведомление-«плитка» на рисунке 3 предоставляет пользователям самую важную информацию. Код, генерирующий это уведомление-«плитку», имеет доступ к файлу Excel, который хранится на сервере SharePoint и считывает ежегодные доходы (листинг 3).
Код, который генерирует нижнее уведомление-«плитку», показанное на рисунке 3, имеет доступ к файлу Excel, хранящемуся на сервере SharePoint и считывающему информацию о ежеквартальных доходах (листинг 4).
HttpWebRequest. Вероятно, вы заметили строку кода, которая содержит Util.PostData(url) в листингах 1, 2, 3 и 4. Чтобы вызвать службу ASP.NET MVC 4 и передать уведомление WNS, приемник событий с элементами списка делает запрос HttpWebRequest внутри этого метода (листинг 5).
Когда служба ASP.NET MVC 4 получает запрос, она проверят URL, чтобы определить, какой тип уведомления нужно послать, и вызывает соответствующий код для отсылки уведомления WNS (листинг 6).
Заметьте, что прежде чем использовать WNS, вы должны зарегистрировать свое приложение и получить учетные данные для своей службы. Процесс регистрации приложения при помощи Windows Store Dashboard и другие инструкции описаны в MSDN (http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh913756.aspx). Загляните в мой блог, там есть ссылки на образцы кодов MSDN, которые также иллюстрируют шаблон для SharePoint 2013 (http://toddbaginski.com/blog/).
По мере того как я демонстрирую образцы кодов, вы увидите, что это сравнительно несложный шаблон – код совсем простой. Самое важное –понять и обойти ограничения, которые ассоциируются с библиотеками WNS (о них я рассказывал выше).
В зависимости от применяемого типа уведомления вызывается один из двух методов в службы ASP.NET MVC 4, чтобы послать уведомление WNS. Оба метода следуют шаблону, задокументированному на сайте MSDN (http://msdn.microsoft.com/en-us/library/windows/apps/xaml/hh913756.aspx). Давайте рассмотрим его.
Метод SendToastNotification. Метод SendToastNotification (листинг 7) отсылает всплывающие уведомления. Первое, что делает метод — это вызов метода GetAccessToken. Метод GetAccessToken посылает ID клиента и секретный ключ службе Windows Live ID Service и возвращает токен доступа для соединения с WNS. ID клиента и секретный ключ предоставляются тогда, когда вы регистрируете свое приложение на Windows Store Dashboard.
Переменная channelUrl (листинг 7) обращается к каналу, который вы установили с WNS. Канал позволяет приложению (в данном случае, службе ASP.NET MVC 4) взаимодействовать с WNS.
Данные переменной определяет часть пакета данных, которые отсылаются на WNS через POST HttpWebRequest (листинг 7). Данные переменной комбинируются с названием и конвертируются в массив байтов, прежде чем пакет данных отсылается WNS. WNS использует пакет данных для передачи уведомлений приложению Windows 8. Заметьте, что токен доступа добавляется к заголовкам запроса для его аутентификации.
Метод SendTileNotification. Метод SendTileNotification (листинг 8) отсылает уведомления-«плитки». Он следует такому же шаблону, как и метод SendToastNotification, за исключением того, что он отсылает уведомления-«плитки». Обратите внимание, что этот метод поддерживает отправку нескольких уведомлений-«плиток» через одну точку входа. Параметр tileNotificationType определяет, какое уведомление-«плитка» отсылается.
Переменные cell1, cell2 и cell3 в листинге 8 представляют данные из рабочей книги Excel, которые пересылаются через URL, назначенный соответствующему приемнику событий с элементами списка, для вызова службы ASP.NET MVC 4. Их значения являются частью уведомлений на «плитке», показанных на рисунке 3, которые представляют финансовые данные.
Наконец, переменная imageUrl в листинге 8 включает путь к образу на сервере SharePoint, который представляет собой значок диаграммы, появляющийся на уведомлении-«плитке», как на рисунке 3.
Запросы
Теперь, когда я показал, каким образом отсылать уведомления, давайте вернемся к запросу данных SharePoint из приложения Windows 8. Когда в приложении Windows 8 создается новая задача по сделке, общее значение сметы сохраняется в столбце доходов в списке RFQ. Столбец LeadStatusValue обновляется значением со статусом «создан». Это действие запускает метод ItemUpdated в приемнике событий с элементами списка, который в свою очередь посылает сотрудникам уведомления через WNS. Таким образом сотрудники узнают, что эта часть процесса RFQ завершена. Приложение Windows 8 использует SharePoint 2010 ListData из API протокола Representational State Transfer (REST) для обновления столбца значений. Листинг 9 демонстрирует, как этот API вызывается из JavaScript в приложении Windows 8.
Вы можете производить и другие операции при помощи SharePoint 2010 ListData REST API для выполнения всего набора операций создания, чтения, обновления и удаления в списках SharePoint из приложений Windows 8.
Уведомления правят бизнесом
Вы можете комбинировать SharePoint, Windows 8 и WNS для создания линейки бизнес-приложений следующего поколения, которые сообщают пользователям новейшую информацию и помогают предприятиям работать максимально эффективно. Уведомления могут поступать на пользовательский компьютер или мобильное устройство (через приложения Windows Phone), что делает их универсальными. В данной статье представлен сценарий, уведомляющий сотрудников о статусе RFQ и задачах, которые должны быть завершены в ходе процесса, но шаблон может быть применен и во многих других ситуациях.
Листинг 1. Код, который генерирует всплывающее уведомление через службу ASP.NET MVC 4
string toastTitle = Convert.ToString(properties.AfterProperties[«Title»]); string company = Convert.ToString(properties.AfterProperties[«Company»]); string toast = string.Format(«Please create the estimate for the {0} project for company {1}.», toastTitle, company); string url = PostUrl + string.Format(«?itemTitle={0}¬Type={1}», Util.HttpEncode(toast), NotificationType.Toast); Util.PostData(url);
Листинг 2. Код, который генерирует уведомление о новой задаче через службу ASP.NET MVC 4
string tileTitle = «A new sales lead has been entered into the system»; url = PostUrl + string.Format(«?itemTitle={0}¬Type={1}&tileType={2}&imageUrl={3}», Util.HttpEncode(tileTitle), NotificationType.Tile, TileType.TileWideText03, Util.HttpEncode(properties.WebUrl + «/Shared%20Documents/star.jpg»)); Util.PostData(url);
Листинг 3. Код, генерирующий уведомление о ежегодных доходах через службу ASP.NET MVC 4
tileTitle = «Yearly Rev»; string imageUrl = properties.WebUrl + Util.GetYearlyRevImage(company); url = PostUrl + string.Format(«?itemTitle={0}¬Type={1}» + «&tileType={2}&imageUrl={3}&cell1={4}» + «&cell2={5}&cell3={6}», Util.HttpEncode(tileTitle), NotificationType.Tile, TileType.TileWideImage, Util.HttpEncode(imageUrl), Util.GetACellValueFromExcel(company, «2010», web), Util.GetACellValueFromExcel(company, «2011», web), Util.GetACellValueFromExcel(company, «2012», web)); Util.PostData(url);
Листинг 4. Код, генерирующий уведомление об информации о ежеквартальных доходах через службу ASP.NET MVC 4
tileTitle = «Quarterly Rev»; imageUrl = properties.WebUrl + Util.GetQuarterlyRevImage(company); url = PostUrl + string.Format(«?itemTitle={0}¬Type={1}» + «&tileType={2}&imageUrl={3}&cell1={4}&cell2={5}&cell3={6}», Util.HttpEncode(tileTitle), NotificationType.Tile, TileType.TileWideSmallImageAndText01, Util.HttpEncode(imageUrl), Util.GetACellValueFromExcel(company, «2011 Q4», web), Util.GetACellValueFromExcel(company, «2012 Q1», web), Util.GetACellValueFromExcel(company, «2012 Q2», web)); Util.PostData(url);
Листинг 5. Вызов службы ASP.NET MVC 4 из приемника событий с элементами списка
public static void PostData(string purl) { try { HttpWebRequest req = (HttpWebRequest)WebRequest.Create(purl); req.Timeout = 90000; req.Method = «Post»; req.ContentType = «application/x-www-form-urlencoded»; req.ContentLength = 0; HttpWebResponse rep = (HttpWebResponse)req.GetResponse(); } catch (Exception ex) { } }
Листинг 6. Определение типа уведомления для подготовки вызова WNS
[HttpPost] public ActionResult SendNotification() { try { ChannelURL = Util.GetConfigValue(«channelUrl»); NotificationType notificationType = Util.GetNotificationType(Convert.ToString(Request[«notType»])); string title =Util.HttpDecode(Convert.ToString(Request[«itemTitle»])); if (notificationType == NotificationType.Tile) { TileType tileType = Util.GetTileType(Convert.ToString(Request[«tileType»])); string imageUrl = Convert.ToString(Request[«imageUrl»]); Util.SendTileNotification(title, imageUrl, ChannelURL, tileType); } else { Util.SendToastNotification(title, ChannelURL); } } catch { } return new EmptyResult(); }
Листинг 7. Отправка всплывающего уведомления через WNS
public static void SendToastNotification(string title, string channelUrl) { string accessToken = GetAccessToken(); var subscriptionUri = new Uri(channelUrl); var request = (HttpWebRequest)WebRequest.Create(subscriptionUri); request.Method = «POST»; request.ContentType = «text/xml»; request.Headers = new WebHeaderCollection(); request.Headers.Add(«X-WNS-Type», «wns/toast»); request.Headers.Add(«Authorization», «Bearer» + accessToken); string data = «»; byte[] notificationMessage = Encoding.Default.GetBytes(string.Format(data, title)); request.ContentLength = notificationMessage.Length; using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(notificationMessage, 0, notificationMessage.Length); } var response = (HttpWebResponse)request.GetResponse(); } }» + « }» + « {0}
Листинг 8. Отправка уведомлений-«плиток» через WNS
public static void SendTileNotification(string title, string imageUrl, string channelUrl, TileType tileNotificationType) { var subscriptionUri = new Uri(channelUrl); string accessToken = GetAccessToken(); var request = (HttpWebRequest)WebRequest.Create(subscriptionUri); request.Method = «POST»; request.ContentType = «text/xml»; request.Headers = new WebHeaderCollection(); request.Headers.Add(«X-WNS-Type», «wns/tile»); string data = string.Empty; if (tileNotificationType == TileType.TileWideText03) { request.Headers.Add(«X-WNS-Tag», «aa11»); data = string.Format(«» + «», title); } string cell1 = Convert.ToString(System.Web.HttpContext.Current.Request[«cell1»]); string cell2 = Convert.ToString(System.Web.HttpContext.Current.Request[«cell2»]); string cell3 = Convert.ToString(System.Web.HttpContext.Current.Request[«cell3»]); if (tileNotificationType == TileType.TileWideImage) { request.Headers.Add(«X-WNS-Tag», «aa22»); imageUrl = « » + « » + « » + «{0} » + «/img/chart.png»; data = string.Format(«» + « », imageUrl, title, cell1, cell2, cell3); } if (tileNotificationType == TileType.TileWideSmallImageAndText01) { request.Headers.Add(«X-WNS-Tag», «aa33»); imageUrl = «http:// » + « » + « » + «» + « {1} » + «2010: ${2} » + «2011: ${3} » + «2012: ${4} » + «» + « /img/chart.png»; data = string.Format(«» + « », imageUrl, title, cell1, cell2, cell3); } request.Headers.Add(«X-WNS-TTL», «600000»); request.Headers.Add(«Authorization», «Bearer» + accessToken); byte[] notificationMessage = Encoding.Default.GetBytes(data); request.ContentLength = notificationMessage.Length; using (Stream requestStream = request.GetRequestStream()) { requestStream.Write(notificationMessage, 0, notificationMessage.Length); } var response = (HttpWebResponse)request.GetResponse(); } » + « » + « » + «» + « {1} » + «2011 Q4: ${2} » + «2012 Q1: ${3} » + «2012 Q2: ${4} » + «» + «
Листинг 9. Использование данных SharePoint ListData API для обновления элемента списка SharePoint
function putSharePointData(item, handle) { var spListItemRestSrvUri = WinJS.Resources.getString(«intranet.contoso.com»).value + «/_vti_bin/listdata.svc/RFQ(» + item.Id + «)", spItem = { Revenue: item.Revenue, LeadStatusValue:»Estimate Created« }, etag = item._etag; WinJS.xhr({ url: spListItemRestSrvUri, type:»POST«, data: JSON.stringify(spItem), headers: { accept: 'application/json', »Content-Type«: 'application/json; charset=utf-8', »If-Match«: etag, »X-HTTP-Method«: "MERGE» } }). then( function complete(result) { handle(); }, function error(error) { logger.log(«Not able to put data to SharePoint», «error», «spData.js», error.status, error.statusText); }); }