Описание проблемы:

Имеется анонимный веб-сервис, который обрабатывает внешние запросы. Внутри сервиса как положено определяю системное подключение SystemUserConnection, для обеспечения работоспособности бизнес-процессов при работе с Entity добавляю соответствующую строку.

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

По причине того, что внутри вызываемого бизнес-процесса вызывается класс для генерации печатных форм ReportService и он никак не хочет работать с системным подключением SystemUserConnection было решено запускать процесс через ProcessEngineService.svc с предварительной аутентификацией посредством AuthService.svc.

Суть проблемы: при запросе из postman к методу моего анонимного веб-сервиса на стенде c обычным протоколом (http) отрабатывает все хорошо, на стенде с защищенным протоколом (https) возникает исключение при аутентификации «The underlying connection was closed: An unexpected error occurred on a send.».

Пробовались попытки получить cookies из системного контекста и перегнать их в ProcessEngineService.svc.

cookies = new CookieContainer();
var sourceCookies = HttpContext.Current.Request.Cookies;
for (int i = 0; i < sourceCookies.Count; i++)
{
    System.Web.HttpCookie cSource = sourceCookies[i];
    Cookie cookieTarget = new Cookie()
    {
        Domain = HttpContext.Current.Request.UserHostAddress,
        Name = cSource.Name,
        Path = cSource.Path,
        Secure = cSource.Secure,
        Value = cSource.Value
    };
    cookies.Add(cookieTarget);
}
HttpWebRequest httpWebRequest = WebRequest.Create(requestString)
                                    as HttpWebRequest;
httpWebRequest.Method = "GET";
httpWebRequest.CookieContainer = cookies;
httpWebRequest.GetResponse();

При таком подходе возникает тоже исключение «The underlying connection was closed: An unexpected error occurred on a send.», но уже при вызове метода httpWebRequest.GetResponse();

Как решить данную проблему?

Нравится

1 комментарий

Ильдар, добрый день!

 

Скажите, Вы смотрели логи приложения? Возможно там есть более развернутый текст ошибки. Можете предоставить записи из логов, которые возникли в момент воспроизведения проблемы?

Показать все комментарии

Добрый день!

При вызове скрипта генерирования печатной формы в бизнес-процессе он падает с ошибкой:

System.NullReferenceException: Object reference not set to an instance of an object.

   at Terrasoft.Configuration.ReportService.ReportService.GetSchemaNameByTemplateId(Guid templateId)

Определили, что это возникает только когда бизнес-процесс вызывается сигналом или событием, т.е. только тогда когда процесс запускается от имени Supervisor. Запускаем вручную - всё работает отлично.

Вопросы: как можно заменить Supervisor на другого пользователя? Или может посоветуете как получить UserConnection другого пользователя для выполнения ReportService? Возможно ли обойтись в ReportService без UserConnection?

Спасибо!

Нравится

6 комментариев

а как происходит инициализация ReportService в бп?

Ранее тема обсуждалась тут и тут. В ReportService в логике функций GenerateMSWordReport или GenerateDevExpressReport есть фрагменты, которые позволяют его запускать только при работе из браузера, но не в фоновом режиме с сервера, когда UserConnection нет. В комментариях один из участников рассказал, что в итоге переделал этот сервис, чтобы не использовать UserConnection. А другой предложил запускать от имени какого-то пользователя посредством ProcessEngineService, так работает нормально.

Варфоломеев Данила,

Процесс запускается через задание-сценарий вызовом 

GenerateMSWordReport, в который передаются параметры бизнес-процесса и UserConnection

 

Зверев Александр,

Спасибо вам за информацию!

Мы заметили, что новый функционал в 7.13.2 "Фоновое выполнение операции" предназначен для запуска фоновых задач, которые требуют UserConnection. Я правильно понимаю, что с помощью этого функционала можно создать UserConnection для передачи в GenerateMSWordReport? (https://academy.terrasoft.ru/documents/technic-sdk/7-13/fonovoe-vypolne…)

Зверев Александр,

и может вы знаете как на время изменить в процессе системную настройку текущего системного пользователя по умолчанию с Supervisor на другого пользователя, чтобы таким образом взять его UserConnection?

Дело не в том, что это конкретно Supervisor. Если под Supervisor зайти в систему и по действию построить отчёт, всё отработает.

Варианты по ссылкам предлагались ещё до появления 7.13.2, можете проверить и этот механизм.

Показать все комментарии

Коллеги, добрый день.

Подскажите, пожалуйста, возможно кто-то сталкивался с аналогичной проблемой.

Есть бизнес- процесс, который в числе прочих действий генерирует печатную форму и отправляет её по Email как аттачмент.

Если запускать этот БП вручную, он успешно отрабатывает. При вызове из задания (QuartzScheduler) - падает на шаге генерации ПФ.

ПФ генерируется в ScriptTask с помощью вызова ReportService:

var reportData = reportService.GenerateMSWordReport(templateId, recordId, convertInPDF);

Шаг падает со следующим Exception:

System.NullReferenceException: Object reference not set to an instance of an object.
   at Terrasoft.Configuration.ReportService.ReportService..ctor()
   at Terrasoft.Core.Process.UsrOutdatedTSActNotif.ScriptTask2Execute(ProcessExecutingContext context)
   at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

Нравится

3 комментария

Здравствуйте, вероятно при работе планировщика нет userconnection-а, попробуйте из стороннего c# кода вызвать свой бп с формированием отчета:
https://academy.terrasoft.ru/documents/technic-sdk/7-7-0/zapusk-process…
если получится, то сделайте бп который будет работать по планировщику, и вызывать таким же образом образом другой бп с формированием отчета.
Такой вызов должен эмулировать нормальный заход пользователя на сайт (авторизация) и запуск процесса как бы в ручном режиме.

Илья,
большое спасибо, помогло.

Единственный минус - в таком случае придётся заводить служебного пользователя для поторяющизся задач и хранить где-то его логин/пароль в открытом виде.

Возможно есть какой-то более простой способ получить UserConnection в БП, запускаемом из Quartz?

Здравствуйте!

В создании дополнительно пользователя нет необходимости.
Будет подтягиваться userconnection пользователя, которого вы укажите при создании job’а.
Условно:

string userName = userConnection.CurrentUser.Name;
AppScheduler.ScheduleMinutelyProcessJob(schedulerJobName, schedulerJobGroupName, jobProcessName, solutionName, userName, minutleyInterval, isSystemUser : true);

Показать все комментарии