Create Microsoft Workflow Foundation project using InfoPath Form for control state of request

Всем привет.

В очередной раз пишу статью об использовании некоторых, полезных вещах в реальной жизни программиста. Итак, сегодня речь пойдет об использовании технологии Microsoft Workflow Foundation и Microsoft InfoPath Form.

Задача: Написать несколько InfoPath форм (которые потом будут встроены в Sharepoint portal), с помощью которых пользователь будет иметь возможность провести заявку через цепочку ключевых этапов. Среди основных этапов в моем случае были: создание, отправка, подтверждение, отмена, возможность повторить подтверждения и так далее.

Средства: Итак, как мы видим из вышеуказанной задачи, будущее решение основывается на использовании технологии .NET Framework. Из ключевых технологий, которые будут применены, можно отметить Microsoft Workflow Foundation для реализации состояния заявки. Посредником между формой и Workflow будет выступать веб - сервис.

Реализация: Приступая к разработке данного решения, я рекомендую начать с front-end-а. Ибо именно веб-сайт, и веб-сервисы будут неопределенное время Вашими ключевыми зацепками в процессе тестирования логики.

Открываем Visual Studio (я реализовывал все на Microsoft Visual Studio 2008), создаем новый веб-сайт. Как Вы можете видеть, на рисунке 1, я назвал сайт WorkflowFrontEnd. Рисунок 1 – Общая структура проекта. Сразу же добавляем веб-сервис, который и будет выступать посредником между работой пользователя через InfoPath Form и рабочим экземпляром класса Workflow Foundation. Следует сказать, что этот веб-сервис будет выступать в роли не только посредника, но и хостера среды исполнения всех экземпляров workflow. Я создал два веб-сервиса: WorkflowControll.asmx и WorkflowMediator.asmx. В данном примере я буду использовать только второй сервис. Именно ссылку на него нужно будет создать в коде InfoPath Form.

Продолжая работу над потоком исполнения, вначале необходимо создать все классы и интерфейсы, которые будут обслуживать поток. Добавляем к существующему решению, новый Class Library проект. Так, начнем пожалуй, с классов, которые будут обеспечивать передачу данных при переходе на другой шаг. В моей случае было создано два класса: StatusEventArgs и DataEventArgs унаследованных от ExternalDataEventArgs. Именно эти два класса будут служит некими коммуникаторами при передаче аргументов в каждый шаг.

 [Serializable()]
    public class DataEventArgs : ExternalDataEventArgs
    {
        #region Fields
 
        private EventInfo _Info;
        public EventInfo Information
        {
            get { return _Info; }
            set { _Info = value; }
        }
 
        #endregion
 
        public DataEventArgs(Guid instanceId, EventInfo info)
            : base(instanceId)
        {
            WaitForIdle = true;
            _Info = info;
        }
}

Из кода выше, Вы можете понять что класс должен быть сериализируемым (для передачи через веб-сервис), и сообственно наследоваться от ExternalDataEventArgs. Похожим образом объявляем второй класс.

Логика работы потока исполнения (в нашем, конкретном случае) очень проста. Мы ожидаем события от веб-сервиса, и если это события именно то, что ожидает Workflow – все ок, активируем шаг и исполняем внутреннюю его логику. В случае «промаха» - получаем EventDeliveryFailedException исключение. Поскольку, в свойствах на ожидания конкретного события нужно указать интерфейс, который описывает его – давайте реализуем этот интерфейс.

[ExternalDataExchange()]
public interface IExchangeWorkflowService
{
      event EventHandler<DataEventArgs> OnCreating;
      event EventHandler<StatusEventArgs> OnSelecting;
      event EventHandler<DataEventArgs> OnCompleting;
      event EventHandler<DataEventArgs> OnProcessingStep;
}