Поделиться через


Вызов веб-служб из рабочих процессов 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, которое было передано в качестве аргумента рабочего процесса.

Снимок экрана с текстовым полем для ввода URL-адреса веб-службы отправки данных по HTTP


Запрос POST также передает значение страны, которое хранится в элементе списка, в котором работает рабочий процесс.

Снимок экрана с сеткой свойств для отправки данных по HTTP


Рабочий процесс отправляет значения appWebUrl и contextToken веб-приложению через заголовки запросов. Заголовки также устанавливают типы контента для отправки и приема запросов.

Снимок экрана с сеткой для добавления заголовков запросов для отправки данных по HTTP

Если рабочий процесс утвержден, он изменяет значение поля 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("'", "''") + "'&amp;$select=CompanyName".

Действие HttpSend должно быть настроено как запрос GET с заголовком Accept, который указывает JSON без метаданных: application/json;odata=nometadata.

Снимок экрана с сеткой отправки данных по HTTP, настроенной как запрос GET

Снимок экрана с сеткой заголовков запросов для отправки данных по HTTP


Если пользователь выбрал 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 будут обновлены в будущем, вам, возможно, не потребуется использовать это временное решение.

Развертывание рабочего процесса на хост-сайте

  1. Откройте контекстное меню (щелкните правой кнопкой мыши) для проекта надстройки Workflow.AssociateToHostWeb в обозревателе проекта и выберите Опубликовать. Вы увидите окно с кнопкой Упаковка приложения.

    Снимок экрана со страницей публикации примера надстройки

  2. При выборе пакета приложения Visual Studio создает файл Workflow.AssociateToHostWeb.app в каталоге bin\Debug\app.publish\1.0.0.0 решения. Этот файл .app является типом ZIP-файла.

  3. Извлеките содержимое файла, сначала изменив расширение файла на .zip.

  4. В извлеченном каталоге найдите и откройте XML-файл с именем WorkflowManifest.xml. Файл пуст.

  5. Добавьте в файл следующий фрагмент XML и сохраните файл.

       <SPIntegratedWorkflow xmlns="http://schemas.microsoft.com/sharepoint/2014/app/integratedworkflow">
         <IntegratedApp>true</IntegratedApp>
       </SPIntegratedWorkflow>
    
  6. Выберите все файлы в извлеченной папке, а затем откройте контекстное меню (щелкните правой кнопкой мыши) для файлов и выберите Отправить в>сжатую (ZIP) папку.

  7. В только что созданном ZIP-файле измените расширение файла на .app. Теперь у вас должен быть новый пакет Workflow.AssociateToHostWeb.app, содержащий обновленный файл WorkflowManifest.xml.

  8. Добавьте надстройку в каталог приложений.

  9. Установите надстройку на хост-сайт.

  10. Перейдите к списку на хост-сайте и выберите параметр Список редактирования в верхнем левом углу страницы. Вы увидите раскрывающееся менюПараметры рабочего процесса.

    Снимок экрана с параметрами рабочих процессов для списка

  11. Выберите Добавить рабочий процесс в раскрывающемся меню.

  12. Теперь на рисунке ниже вы увидите параметр выделения, похожий на следующее изображение. Выберите надстройку Workflow.AssociateToHostWeb в списке доступных параметров.

    Снимок экрана со страницей параметров

Теперь рабочий процесс развернут на хост-сайте и связан со списком на хост-сайте. Вы можете запускать рабочий процесс вручную или обновлять его в Visual Studio, чтобы он запускался другими способами.

Дополнительные ресурсы