Вызов веб-служб из рабочих процессов SharePoint
Модель надстройки SharePoint можно использовать для создания и развертывания рабочих процессов, которые работают на сайте надстройки или хост-сайте. Эти процессы могут взаимодействовать с удаленными частями надстроек, размещаемых у поставщика.
Кроме того, рабочие процессы могут вызывать удаленные веб-службы, содержащие важные бизнес-данные, одним из двух способов:
Путем передачи сведений запроса в удаленно размещенную часть надстройки. Затем удаленное веб-приложение вызывает веб-службу и передает сведения обратно в SharePoint.
Путем запроса веб-службы с помощью веб-прокси SharePoint. Рабочий процесс передает результаты запроса в удаленно размещенную часть надстройки, которая затем передает сведения в SharePoint.
Сведения, полученные из веб-службы, могут храниться в списках SharePoint.
В этой статье описаны три примера кода, которые показывают, как вызывать веб-службы из рабочих процессов, как указано в следующей таблице. В первых двух примерах рабочие процессы и списки развертываются на веб-сайте надстройки при ее установке. В последнем примере представлена базовая оболочка рабочего процесса и инструкции по его развертыванию в хост-сети и связыванию со списком в хост-сети.
Задачи рабочих процессов и связанные примеры
Задача | Пример |
---|---|
Вызов настраиваемых веб-служб из рабочего процесса. | Workflow.CallCustomService |
Вызов пользовательской веб-службы из рабочего процесса и обновление SharePoint с помощью веб-прокси SharePoint. | Workflow.CallServiceUpdateSPViaProxy |
Сопоставление рабочего процесса с хост-сайтом. | Workflow.AssociateToHostWeb |
Вызов настраиваемых веб-служб из бизнес-процесса
В этом примере Workflow.CallCustomService показано, как создать рабочий процесс, который вызывает пользовательскую веб-службу, обновляющую данные списков SharePoint. В нем также показано, как разработать надстройку, размещаемую у поставщика, чтобы она запрашивала веб-службу с помощью удаленно размещенного веб-приложения, которое развертывается вместе с надстройкой. Этот пример полезен, если вы хотите, чтобы все взаимодействия с веб-службой обрабатывались удаленной частью надстройки, размещенной у поставщика.
Пример работает путем запуска рабочего процесса из удаленного веб-приложения. Этот рабочий процесс передает сведения о запросе, отправленные пользователем, в удаленное веб-приложение, которое затем использует эти сведения для создания запроса в веб-службу OData Northwind. Запрос возвращает поставщиков продуктов для данной страны. После получения этих сведений удаленное веб-приложение обновляет список поставщиков продуктов, развернутый надстройкой на сайте надстройки.
Примечание.
На странице примера Workflow.CallCustomService содержатся инструкции по развертыванию этой надстройки. Вы также можете развернуть и протестировать отладку F5 в Visual Studio, следуя инструкциям в записи блога Отладка рабочих процессов SharePoint 2013 с помощью Visual Studio 2013.
На начальной странице примера надстройки Workflow.CallCustomService есть раскрывающееся меню, в котором можно выбрать страну, для которой нужно создать список поставщиков продуктов.
Кнопка Create на экране вызывает метод Create в файле Controllers\PartSuppliersController.cs, который создает новую запись в списке поставщиков частей на веб-сайте надстройки. Метод Create затем вызывает метод Add, определенный в файле Services\PartSuppliersService.cs. Последовательность показана в следующих двух примерах кода.
Метод Create
public ActionResult Create(string country, string spHostUrl)
{
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
using (var clientContext = spContext.CreateUserClientContextForSPAppWeb())
{
var service = new PartSuppliersService(clientContext);
var id = service.GetIdByCountry(country);
if (id == null)
{
id = service.Add(country);
TempData["Message"] = "Part Supplier Successfully Created!";
}
else
TempData["ErrorMessage"] = string.Format("Failed to Create The Part Supplier: There's already a Part Supplier who's country is {0}.", country);
return RedirectToAction("Details", new { id = id.Value, SPHostUrl = spHostUrl });
}
}
Метод Add
public int Add(string country)
{
var item = list.AddItem(new ListItemCreationInformation());
item["Country"] = country;
item.Update();
clientContext.ExecuteQuery();
return item.Id;
}
После создания этого элемента списка надстройка представляет кнопку Запуск рабочего процесса, которая запускает рабочий процесс утверждения.
При нажатии кнопки Запуск рабочего процесса запускается метод StartWorkflow, определенный в файле Controllers\PartSuppliersController.cs. Этот метод упаковывает URL-адрес сайта надстройки, URL-адрес веб-службы (для удаленного веб-приложения, а не для веб-службы Northwind) и значения маркера контекста и передает их методу StartWorkflow. Методу PartSuppliersService требуется маркер контекста для взаимодействия с SharePoint.
public ActionResult StartWorkflow(int id, Guid workflowSubscriptionId, string spHostUrl)
{
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext) as SharePointAcsContext;
var webServiceUrl = Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Data" }, Request.Url.Scheme);
var payload = new Dictionary<string, object>
{
{ "appWebUrl", spContext.SPAppWebUrl.ToString() },
{ "webServiceUrl", webServiceUrl },
{ "contextToken", spContext.ContextToken }
};
using (var clientContext = spContext.CreateUserClientContextForSPAppWeb())
{
var service = new PartSuppliersService(clientContext);
service.StartWorkflow(workflowSubscriptionId, id, payload);
}
TempData["Message"] = "Workflow Successfully Started!";
return RedirectToAction("Details", new { id = id, SPHostUrl = spHostUrl });
}
Затем метод StartWorkflow создает экземпляр рабочего процесса и передает в рабочий процесс три значения (appWebUrl, webServiceUrl, contextToken), хранящиеся в переменной полезной нагрузки.
{
var workflowServicesManager = new WorkflowServicesManager(clientContext, clientContext.Web);
var subscriptionService = workflowServicesManager.GetWorkflowSubscriptionService();
var subscription = subscriptionService.GetSubscription(subscriptionId);
var instanceService = workflowServicesManager.GetWorkflowInstanceService();
instanceService.StartWorkflowOnListItem(subscription, itemId, payload);
clientContext.ExecuteQuery();
}
После начала рабочего процесса он отправляет HTTP-запрос POST в удаленно размещенное веб-приложение. Этот запрос сообщает веб-приложению об обновлении списка поставщиков для страны, которую пользователь только что добавил. Файл Controllers\DataController.cs содержит метод POST, который получает содержимое этого запроса.
public void Post([FromBody]string country)
{
var supplierNames = GetSupplierNames(country);
UpdateSuppliers(country, supplierNames);
}
Метод GetSupplierNames (в файле Controllers\DataController.cs) создает и выполняет запрос LINQ в веб-службе Northwind OData для всех поставщиков, связанных с выбранной страной.
private string[] GetSupplierNames(string country)
{
Uri uri = new Uri("http://services.odata.org/V3/Northwind/Northwind.svc");
var entities = new NorthwindEntities(uri);
var names = entities.Suppliers
.Where(s => s.Country == country)
.AsEnumerable()
.Select(s => s.CompanyName)
.ToArray();
return names;
}
Метод UpdateSuppliers затем обновляет поле Поставщики добавленного элемента списка.
private void UpdateSuppliers(string country, string[] supplierNames)
{
var request = HttpContext.Current.Request;
var authority = request.Url.Authority;
var spAppWebUrl = request.Headers["SPAppWebUrl"];
var contextToken = request.Headers["SPContextToken"];
using (var clientContext = TokenHelper.GetClientContextWithContextToken(
spAppWebUrl, contextToken, authority))
{
var service = new PartSuppliersService(clientContext);
service.UpdateSuppliers(country, supplierNames);
}
}
Если вы посмотрите на представление конструктора файла workflow.xaml в каталоге "Утверждение поставщиков" проекта надстройки, вы увидите (выбрав вкладку Аргументы в левом нижнем углу представления конструктора), что рабочий процесс сохраняет три значения в переменной полезной нагрузки, передаваемой ему в качестве аргументов рабочего процесса.
Действие HttpSend происходит до утверждения рабочего процесса. Это действие отправляет запрос POST удаленному веб-приложению, который вызывает веб-службу Northwind, а затем обновление элемента списка (со списком поставщиков). Это действие настроено на отправку запроса значению webServiceUrl, которое было передано в качестве аргумента рабочего процесса.
Запрос POST также передает значение страны, которое хранится в элементе списка, в котором работает рабочий процесс.
Рабочий процесс отправляет значения appWebUrl и contextToken веб-приложению через заголовки запросов. Заголовки также устанавливают типы контента для отправки и приема запросов.
Если рабочий процесс утвержден, он изменяет значение поля isApproved элемента списка на true.
Вызов пользовательской веб-службы из рабочего процесса и обновление SharePoint с помощью веб-прокси SharePoint
В примере Workflow.CallServiceUpdateSPViaProxy показано, как разработать надстройку, размещаемую у поставщика, для запроса веб-службы и последующей передачи этих сведений в список SharePoint через веб-прокси SharePoint.
В примере показана задача, которая полезна, если требуется инкапсулировать все взаимодействия с веб-службой, чтобы они обрабатывались непосредственно рабочим процессом. Использование веб-прокси упрощает обновление логики удаленного веб-приложения без обновления экземпляра рабочего процесса. Если вы не используете прокси-сервер и вам необходимо обновить логику в веб-приложении, необходимо удалить существующие экземпляры рабочего процесса, а затем повторно развернуть надстройку. По этой причине мы рекомендуем использовать этот дизайн, если вам необходимо вызвать удаленную веб-службу.
Примечание.
На странице примера Workflow.CallServiceUpdateSPViaProxy содержатся инструкции по развертыванию этой надстройки. Вы также можете развернуть и протестировать надстройку с использованием отладки F5 в Visual Studio, следуя инструкциям в записи блога Отладка рабочих процессов SharePoint 2013 с помощью Visual Studio 2013.
Пример запускает рабочий процесс из удаленного веб-приложения. Этот рабочий процесс передает сведения запроса, отправленные пользователем, в веб-службу OData Northwind. Запрос возвращает поставщиков продуктов для данной страны. После получения отклика веб-службы рабочий процесс передает сведения из отклика в удаленное веб-приложение. Удаленное веб-приложение затем обновляет список поставщиков продуктов, развернутый надстройкой на сайте надстройки.
При запуске примера надстройки Workflow.CallServiceUpdateSPViaProxy начальная страница включает раскрывающееся меню, в котором можно выбрать страну, для которой нужно создать список поставщиков продуктов.
Кнопка Create вызывает метод в файле Controllers\PartSuppliersController.cs, который создает новую запись в списке поставщиков частей на веб-сайте надстройки. Метод Create в этом файле вызывает метод Add, определенный в файле Services\PartSuppliersService.cs. Оба метода показаны в следующих двух примерах кода.
Метод Create
public ActionResult Create(string country, string spHostUrl)
{
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
using (var clientContext = spContext.CreateUserClientContextForSPAppWeb())
{
var service = new PartSuppliersService(clientContext);
var id = service.GetIdByCountry(country);
if (id == null)
{
id = service.Add(country);
TempData["Message"] = "Part Supplier Successfully Created!";
}
else
TempData["ErrorMessage"] = string.Format("Failed to Create The Part Supplier: There's already a Part Supplier who's country is {0}.", country);
return RedirectToAction("Details", new { id = id.Value, SPHostUrl = spHostUrl });
}
}
Метод Add
public int Add(string country)
{
var item = list.AddItem(new ListItemCreationInformation());
item["Country"] = country;
item.Update();
clientContext.ExecuteQuery();
return item.Id;
}
После создания этого элемента списка надстройка представляет кнопку Запуск рабочего процесса, которая запускает рабочий процесс утверждения.
При нажатии кнопки Запуск рабочего процесса запускается метод StartWorkflow в файле Controllers\PartSuppliersController.cs. Этот метод упаковывает URL-адрес сайта надстройки, URL-адрес веб-службы (для удаленного веб-приложения, а не для веб-службы Northwind) и передает их методу StartWorkflow в файле Services\PartSuppliersService.cs. Рабочий процесс взаимодействует с удаленным веб-приложением через веб-прокси, а веб-прокси добавляет маркер доступа в заголовок запроса. Поэтому рабочий процесс не передает маркер контекста методу StartWorkflow в этом примере. Код показан в следующем примере.
public ActionResult StartWorkflow(int id, Guid workflowSubscriptionId, string spHostUrl)
{
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
var webServiceUrl = Url.RouteUrl("DefaultApi", new { httproute = "", controller = "Data" }, Request.Url.Scheme);
var payload = new Dictionary<string, object>
{
{ "appWebUrl", spContext.SPAppWebUrl.ToString() },
{ "webServiceUrl", webServiceUrl }
};
using (var clientContext = spContext.CreateUserClientContextForSPAppWeb())
{
var service = new PartSuppliersService(clientContext);
service.StartWorkflow(workflowSubscriptionId, id, payload);
}
TempData["Message"] = "Workflow Successfully Started!";
return RedirectToAction("Details", new { id = id, SPHostUrl = spHostUrl });
}
Метод StartWorkflow создает экземпляр рабочего процесса и передает в рабочий процесс два значения (appWebUrl и webServiceUrl), хранящиеся в переменной полезной нагрузки.
public void StartWorkflow(Guid subscriptionId, int itemId, Dictionary<string, object> payload)
{
var workflowServicesManager = new WorkflowServicesManager(clientContext, clientContext.Web);
var subscriptionService = workflowServicesManager.GetWorkflowSubscriptionService();
var subscription = subscriptionService.GetSubscription(subscriptionId);
var instanceService = workflowServicesManager.GetWorkflowInstanceService();
instanceService.StartWorkflowOnListItem(subscription, itemId, payload);
clientContext.ExecuteQuery();
}
После запуска рабочего процесса и до его утверждения рабочий процесс делает запрос к веб-службе Northwind, чтобы получить список поставщиков для выбранной страны. Для этого используется действие HTTPSend, которое отправляет запрос OData в эту конечную точку: "http://services.odata.org/V3/Northwind/Northwind.svc/Suppliers/?$filter=Country eq '" + country.Replace("'", "''") + "'&$select=CompanyName"
.
Действие HttpSend должно быть настроено как запрос GET с заголовком Accept, который указывает JSON без метаданных: application/json;odata=nometadata
.
Если пользователь выбрал Canada для нового элемента списка поставщиков, например, ответ в формате JSON будет таким, как показано в следующем примере.
{
value: [
{
CompanyName: "Ma Maison"
},
{
CompanyName: "Forêts d'érables"
}
]
}
После начала рабочего процесса он отправляет HTTP-запрос POST, содержащий список поставщиков для удаленно размещенного веб-приложения через прокси-сервер. Это осуществляется с помощью действия HttpSend, которое запрашивает URL-адрес веб-прокси: appWebUrl + "/_api/SP.WebProxy.invoke"
.
Затем рабочий процесс передает список поставщиков, полученный от службы Northwind, путем создания и передачи полезной нагрузки пользовательской службы. Свойства действия Создание полезной нагрузки пользовательской службы содержат список поставщиков и идентификатор страны поставщика.
Действие Создание полезной нагрузки WebProxy создает полезную нагрузку, которая передает содержимое этой полезной нагрузки на URL-адрес веб-прокси.
Свойства для действия полезная нагрузка WebProxy определяют URL-адрес надстройки, длину и тип содержимого запроса POST, а также тип принятия запроса через заголовки запроса.
После того как рабочий процесс сконструирует полезные данные и запрос, он передает запрос веб-прокси с помощью действия HttpSend , настроенного как запрос POST к URL-адресу веб-прокси. Заголовки запросов указывают OData в формате JSON в заголовках Content-Type и Accept.
Метод Post в файле Controllers\DataController.cs принимает содержимое запроса, отправляемого рабочий процессом через веб-прокси. Метод Post в предыдущем примере вызывал метод получения списка поставщиков из Northwind, а также метод обновления соответствующего списка поставщиков SharePoint.
Так как рабочий процесс в этом примере уже запросил службу Northwind, этой версии метода необходимо только обновить список SharePoint. Он также передает URL-адрес сайта надстройки и маркер доступа (который передается веб-прокси) в метод UpdateSuppliers в файле Services\PartSuppliersService.cs, как показано в следующем примере кода.
public void Post(UpdatePartSupplierModel model)
{
var request = HttpContext.Current.Request;
var authority = request.Url.Authority;
var spAppWebUrl = request.Headers["SPAppWebUrl"];
var accessToken = request.Headers["X-SP-AccessToken"];
using (var clientContext = TokenHelper.GetClientContextWithContextToken(spAppWebUrl, accessToken, authority))
{
var service = new PartSuppliersService(clientContext);
service.UpdateSuppliers(model.Id, model.Suppliers.Select(s => s.CompanyName));
}
}
Метод UpdateSuppliers в файле PartSuppliers.cs обновляет поле Поставщики вновь созданного элемента списка.
public void UpdateSuppliers(int id, IEnumerable<string> supplierNames)
{
var item = list.GetItemById(id);
clientContext.Load(item);
clientContext.ExecuteQuery();
string commaSeparatedList = String.Join(",", supplierNames);
item["Suppliers"] = commaSeparatedList;
item.Update();
clientContext.ExecuteQuery();
}
Если рабочий процесс утвержден, он изменяет значение поля isApproved элемента списка на true.
Сопоставление рабочего процесса с хост-сайтом
В примере Workflow.AssociateToHostWeb показано, как развернуть рабочий процесс на хост-сайте и связать его со списком на хост-сайте с помощью средств в Visual Studio. Инструкции для этого примера показывают, как создать рабочий процесс в Visual Studio, развернуть его на хост-сайте и связать его со списком на хост-сайте.
Пример содержит простой рабочий процесс, который может быть связан с любым списком. Инструкции по развертыванию этого рабочего процесса показывают, как обойти текущие ограничения средств рабочего процесса Visual Studio, упаковав надстройку, открыв ее и отредактировав файл конфигурации, а затем вручную упаковав перед развертыванием на хост-сайте.
Открыв этот проект в Visual Studio, вы увидите, что это простой универсальный рабочий процесс, предназначенный для работы с любым списком SharePoint. Кроме списка задач рабочего процесса, он не развертывает ни один список, с которым он может быть связан.
Примечание.
Невозможно выполнить задачу, показанную в этом примере, с помощью Visual Studio 2013. В этом примере предлагается удобное временное решение. Если инструменты Visual Studio будут обновлены в будущем, вам, возможно, не потребуется использовать это временное решение.
Развертывание рабочего процесса на хост-сайте
Откройте контекстное меню (щелкните правой кнопкой мыши) для проекта надстройки Workflow.AssociateToHostWeb в обозревателе проекта и выберите Опубликовать. Вы увидите окно с кнопкой Упаковка приложения.
При выборе пакета приложения Visual Studio создает файл Workflow.AssociateToHostWeb.app в каталоге
bin\Debug\app.publish\1.0.0.0
решения. Этот файл .app является типом ZIP-файла.Извлеките содержимое файла, сначала изменив расширение файла на .zip.
В извлеченном каталоге найдите и откройте XML-файл с именем WorkflowManifest.xml. Файл пуст.
Добавьте в файл следующий фрагмент XML и сохраните файл.
<SPIntegratedWorkflow xmlns="http://schemas.microsoft.com/sharepoint/2014/app/integratedworkflow"> <IntegratedApp>true</IntegratedApp> </SPIntegratedWorkflow>
Выберите все файлы в извлеченной папке, а затем откройте контекстное меню (щелкните правой кнопкой мыши) для файлов и выберите Отправить в>сжатую (ZIP) папку.
В только что созданном ZIP-файле измените расширение файла на .app. Теперь у вас должен быть новый пакет Workflow.AssociateToHostWeb.app, содержащий обновленный файл WorkflowManifest.xml.
Добавьте надстройку в каталог приложений.
Установите надстройку на хост-сайт.
Перейдите к списку на хост-сайте и выберите параметр Список редактирования в верхнем левом углу страницы. Вы увидите раскрывающееся менюПараметры рабочего процесса.
Выберите Добавить рабочий процесс в раскрывающемся меню.
Теперь на рисунке ниже вы увидите параметр выделения, похожий на следующее изображение. Выберите надстройку Workflow.AssociateToHostWeb в списке доступных параметров.
Теперь рабочий процесс развернут на хост-сайте и связан со списком на хост-сайте. Вы можете запускать рабочий процесс вручную или обновлять его в Visual Studio, чтобы он запускался другими способами.