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

Имеется следующий таск : показывать пользователю окно с информацией(предупреждение о неразглашении личной информации) при каждом логине.

Пытались создать процесс, который запускается при добавлении новой записи в объект «User session», но он ни разу не сработал.

Изображение удалено.

Подскажите, пожалуйста, как реализовать данную задачу.

 

Спасибо.

С уважением,

Мария.

Нравится

3 комментария
Лучший ответ

Как вариант в секции init запуск модульного окна на странице EnterpriseIntro (для Sale), ServiceEnterpriseIntro (для Service) и MarketingIntro (для  Marketing). Так как пользователь захрдит по умолчанию на эти страницы, но если страница по умолчанию изменена для пользователя тогда не сработает это

Как вариант в секции init запуск модульного окна на странице EnterpriseIntro (для Sale), ServiceEnterpriseIntro (для Service) и MarketingIntro (для  Marketing). Так как пользователь захрдит по умолчанию на эти страницы, но если страница по умолчанию изменена для пользователя тогда не сработает это

Мария, при логине пользователя вставка в SysUserSession происходит с использованием Insert, из-за чего события не срабатывают. Можно либо, как выше предложил Александр, доработать страницу, открываемую при старте, либо, например, сделать процесс, который будет запускаться по таймеру каждые несколько минут и обрабатывать все новые сессии с момента прошлого запуска.

Добрый день, Мария! У вас получилось решить Вашу задачу?

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

Добрый день!

В проект Terrasoft.Configuration.Tests установил пакеты NuGet "NUnit" и "NUnit3TestAdapter". В тест-кейсах мне нужно сделать запросы в БД, поэтому нужен экземпляр UserConnection. Подскажите, как его получить.

Нравится

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

См. эту тему по поводу TestAppConnection и TestCoreUserConnection.

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

В БП с таймером хочу получить локализованный шаблон email. 

Но при получении правил локализации получаю ошибку (см. https://community.terrasoft.ru/questions/osibka-pri-polucenii-sablona-email-v-fonovom-bp)

Вопрос. Почему ActorUserConnection, которое доступно после отработки таймера, не подходит DefaultLanguageIterator?

Вопрос 2: Можно ли сохранить UserConnection (в параметр или др. способом) для использования после таймера? 

Нравится

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

Игорь, возможности обращения к UserConnection при запуске по таймеру ограничены, вопрос обсуждался по приведенной ссылке. На момент срабатывания таймера пользователя может и не быть. Там же приведены более старые обходные варианты для аналогичных вопросов.

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

Коллеги, здравствуйте!

Подскажите, где происходит сакральный Set("UserConnection", UserConnection) для БП?

Из академического интереса спрашиваю по результатам обсуждения  этого вопроса.

 

Нравится

2 комментария
Лучший ответ

Где то внутри Terrasoft.Core.ProcessEngine.... без исходников или дизасма и не видно :)

Где то внутри Terrasoft.Core.ProcessEngine.... без исходников или дизасма и не видно :)

При запуске процесса из конфигурации, интерпретируемого или компилируемого, UserConnection передаётся извне, как видно из примеров, которые приводил Григорий.

А при запуске через ProcessEngineService там в начале функции ExecuteProcess считывается то самое HttpContext.Current.Session["UserConnection"].

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

Приветствую, коллеги!

Запускается макрос по такой схеме:

  1. БП по таймеру
  2. Подпроцесс
  3. ScriptTask
  4. ReportService
  5. GenerateMSWordReport
  6. Макрос : IExpressionConverter

В макросе надо esq запрос выполнить, пытаюсь получить UserConnection:

 

  • HttpContext.Current.Session["UserConnection"] не работает ибо HttpContext.Current == null
  • Get("UserConnection") - нет метода Get
  • context.UserConnection - нет context в объявленных
  • UserConnection - не переменная, а тип

Как же все таки исхитриццо с UserConnection для esq? можно без него запрос сделать?

 

Нравится

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

См. последний ответ тут.

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

перед тем, как я посмотрел тот последний ответ, все заканчивалось как раз на пункте 4

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

а теперь до пункта 7 добирается и в методе Evaluate на строке с получением UserConnection ломает процесс

Как вариант, использовать SystemUserConnection.

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

Теперь надо создать топик "Как получить SystemUserConnection в макросе?"

Попробуйте (HttpContext.Current.Application["AppConnection"] as AppConnection).SystemUserConnection.

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

не работает, ибо 

HttpContext.Current равно null

в каком месте можно глянуть, как инициализируется UserConnection, который берется из Get<UserConnection>(“UserConnection”) или context.UserConnecrion для БП?

В примере макроса вообще есть получение UserConnection и HttpContext.Current там не null:

_userConnection = (UserConnection)HttpContext.Current.Session["UserConnection"];

 

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

ну я же схему объяснил, печатная форма делается в БП, запускаемом по таймеру

A HttpContext.Current.Session[“UserConnection”] работает только при запуске через сервис

Если иначе никак, можно работать через OData, как во стороннем приложении.

Капец как сложно, мне всего то надо если ИПешник, ИНН без КПП выводить и запятой лишней не было :)

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

Решил - переписал:

1) ExpressionConverterHelper, что бы конструктор принимал параметр типа  UserConnection и присваивал его аналогичного типа свойству и в методе GetValue

var expressionConverter = (IExpressionConverter)Activator.CreateInstance(expressionConverterClass);
if (expressionConverter != null) {
    macrosValue.Data = expressionConverter.Evaluate(value, macrosElement.Argument);
}

поменял на

dynamic expressionConverter = Activator.CreateInstance(expressionConverterClass);
if (expressionConverter != null) {
	PropertyInfo propertyInfo = expressionConverter.GetType().GetProperty("UserConnection");
	if (propertyInfo != null) {
		propertyInfo.SetValue(expressionConverter, UserConnection, null);
	}
	macrosValue.Data = expressionConverter.Evaluate(value, macrosElement.Argument);
}

2) в классе ReportService меняем строку

var expressionConverterHelper = new ExpressionConverterHelper();

на 

var expressionConverterHelper = new ZLExpressionConverterHelper(UserConnection);

3) в макросе в начале пишем:

private UserConnection _userConnection;
public UserConnection UserConnection {
    get {
	    if (_userConnection == null) {
		    _userConnection = (UserConnection)HttpContext.Current?.Session["UserConnection"];
	    };
	    return _userConnection;
	}
    set =&gt; _userConnection = value;
}

потом пользуем UserConnection

 

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

Добрый день!

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

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, можете проверить и этот механизм.

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

В процессе пытаюсь получить UserConnection :

var userConnection = HttpContext.Current.Session["UserConnection"] as UserConnection;

однако получаю ошибку :

System.NullReferenceException: Object reference not set to an instance of an object. at Terrasoft.Core.Process.AppFormToContactSyncProcessMethodsWrapper.AppFormToContactSyncScriptTaskExecute(ProcessExecutingContext context) at Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

В чем может быть причина? Как исправить ?

Нравится

1 комментарий
Лучший ответ

Такое может быть, например, если метод вызван из БП, который запущен по расписанию, тогда никакой сессии не будет. В качестве решения, если это сервис - сделать UserConnection свойством класса с возможностью задать извне, и вызывать сервис как-то так.

var service = MyService();
service.UserConnection = userConnection;
service.MyMethod(param1, param2);

В самом бизнес-процессе UserConnection стоит получать как context.UserConnection или Get<UserConnection>("UserConnection"). Во встроенном процессе просто свойство UserConnection есть.

Такое может быть, например, если метод вызван из БП, который запущен по расписанию, тогда никакой сессии не будет. В качестве решения, если это сервис - сделать UserConnection свойством класса с возможностью задать извне, и вызывать сервис как-то так.

var service = MyService();
service.UserConnection = userConnection;
service.MyMethod(param1, param2);

В самом бизнес-процессе UserConnection стоит получать как context.UserConnection или Get<UserConnection>("UserConnection"). Во встроенном процессе просто свойство UserConnection есть.

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

Есть БП, в нем есть скрипт. в скрипте выполняется некий код, который использует сервис ReportService. Там берется Connection. Если запускать БП вручную - все работает. Если по плану - выбивает ошибку.

Вопрос: Как в БП передать Get("UserConnection"); в userConnection сервиса ReportService? Есть ряд других сервисов, возможно туда тоже нужно будет это передать....

Нравится

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

Почему вы решили что UserConnection не передается?

Вы от какого пользователя запускаете БП по расписанию? Есть ли у єтого ползователя права для рабьоты с  ReportService?

Добавить комментарий

Григорий Чех,

Автозапуск от пользователя что и обычный запуск, вот ошибка:

System.ServiceModel.ServiceActivationException: Set AspNetCompatibilityEnabled true

   в Terrasoft.Web.Common.BaseService.get_UserConnection()

   в Terrasoft.Configuration.ReportService.ReportService.GenerateDevExpressReport(String entitySchemaUId, String reportSchemaId, String recordId, String reportParameters)

   в Terrasoft.Configuration.ReportService.ReportHelper.CreateReport(String entitySchemaUId, String reportSchemaUId, String templateId, String recordId, String reportParameters, Boolean convertInPDF)

   в Terrasoft.Configuration.ReportService.ReportService.CreateReport(String entitySchemaUId, String reportSchemaUId, String templateId, String recordId, String reportParameters, Boolean convertInPDF)

   в Terrasoft.Core.Process.UsrAutoSendNightReportMethodsWrapper.ScriptTask1Execute(ProcessExecutingContext context)

   в Terrasoft.Core.Process.ProcessFlowElement.Execute(ProcessExecutingContext context)

Функциональность сервиса ReportService была разработана под вызов с веба, а не с сервера. Ряд его логики может не работать при вызове с серверной стороны. С GenerateMSWordReport будет аналогично.

Те определять UserConnectionнужно как для сервиса

userConnection = HttpContext.Current.Session["UserConnection"]

Те определять UserConnectionнужно как для сервиса

userConnection = HttpContext.Current.Session["UserConnection"]

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

Дмитрий Степанов,

тоже делал так, но там нужно было несколько функций тока, а тут хз что нужно будет...

Добрый день!

У меня данная проблема отпала при передаче параметра "UserConnection" конструктору ReportService.

var reportService = new Terrasoft.Configuration.ReportService.ReportService(UserConnection);

 

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

Здравствуйте! Такая ситуация когда выполняется вызов метода получения UserConnection

через БП, то возникает ошибка, если на прямую из клиента через сервис, но всё нормально, ошибок нет. В чем здесь дело?

Изображение удалено.

 

Нравится

2 комментария
Лучший ответ

Добрый день, Александр.

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

При написании веб сервисов хорошая практика - не писать код обработки непосредственно в методах сервиса, а писать её в рамках некоторого вспомогательного класса. В класс следует добавить конструктор, который принимает объект UserConnection.

При вызове из метода сервиса, вы можете создать экземпляр данного вспомогательного класса и передать в конструктор экземпляр UserConnection, получив его из объекта HttpContext (как вы делаете в примере), а затем вызвать нужный метод вспомогательного класса.

При необходимости вызвать тот же код в другом месте, вы так же создаете экземпляр данного вспомогательного класса, передаете ему экземпляр UserConnection (способ его получения будет отличаться от использования в сервисе), а затем тек же вызвать нужный метод вспомогательного класса.

Получить экземпляр UserConnection в бизнес-процессах можно следующими способами (в зависимости от того интерпретируемый процесс, или нет):

var userConnection = Get&lt;UserConnection&gt;("UserConnection");
​var userConnection = context.UserConnection;

В рамках процессов объектов можно воспользоваться одноименным свойством - UserConnection.

Добрый день, Александр.

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

При написании веб сервисов хорошая практика - не писать код обработки непосредственно в методах сервиса, а писать её в рамках некоторого вспомогательного класса. В класс следует добавить конструктор, который принимает объект UserConnection.

При вызове из метода сервиса, вы можете создать экземпляр данного вспомогательного класса и передать в конструктор экземпляр UserConnection, получив его из объекта HttpContext (как вы делаете в примере), а затем вызвать нужный метод вспомогательного класса.

При необходимости вызвать тот же код в другом месте, вы так же создаете экземпляр данного вспомогательного класса, передаете ему экземпляр UserConnection (способ его получения будет отличаться от использования в сервисе), а затем тек же вызвать нужный метод вспомогательного класса.

Получить экземпляр UserConnection в бизнес-процессах можно следующими способами (в зависимости от того интерпретируемый процесс, или нет):

var userConnection = Get&lt;UserConnection&gt;("UserConnection");
​var userConnection = context.UserConnection;

В рамках процессов объектов можно воспользоваться одноименным свойством - UserConnection.

Семенов Александр Евгеньевич,

Спасибо большое за ответ, разобрался всё работает)

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

Коллеги, приветствую.

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

В ..\Terrasoft.WebApp\Web.config настроил выгрузку исходных кодов C# в процессе кодогенерации -

    ...
   
   ...

Подключил библиотеки Terrasoft.

Собственно, пытаюсь отладить какой- нибудь простой запрос, вроде такого -

...
var select = new Select(userConnection)
        .Column("Id")
        .Column("Name")
        .From("Contact");
...

- возникает вопрос, как настроить класс UserConnection... Был бы весьма признателен за информацию, без отладчика весьма и весьма грустно.

Спасибо.

--
С уважением, Алексей Быков.

Нравится

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

Я могу, конечно, использовать такой код -

using System.Data.SqlClient;
 
static void Main(string[] args)
{
 
	SqlConnection myConnection = new SqlConnection("user id=sa; password....");
 
	try
	{
		myConnection.Open();
		SqlDataReader myReader = null;
 
		SqlCommand myCommand = new SqlCommand("select Id, Name from Contact", myConnection);
		myReader = myCommand.ExecuteReader();
		while (myReader.Read())
		{
			Console.WriteLine(myReader["Id"].ToString());
			Console.WriteLine(myReader["Name"].ToString());
		}
	}
	catch (Exception e)
	{
		Console.WriteLine(e.ToString());
	}
}

- но как отладить такой -

var select = new Select(userConnection)
        .Column("Id")
        .Column("Name")
        .From("Contact"); 

Алексей, для отладки есть еще ряд флагов в конфигах. Подробнее на скриншоте:

Для отладки нужно приаттачиться VS к вашему процессу w3wp.exe (если их несколько, то можно различать по имени пользователя, от которого запущен пул приложения)

В студии открываете выгруженный код, ставите точки останова в нужных местах.

Для получения текста запросов:
- для классов Select,Update,Delete есть метод GetSqlText() и свойство BuildParametersAsValue, которое нужно устанавливать в true для явного получения параметров;
- для классов ESQ есть метод GetSelectQuery(UserConnection), который возвращает объект класса Select, а из него уже можно получить текст запроса.

Также для просмотра запросов к БД можно использовать SQL Profiler

Александр, спасибо огромное! То, что нужно.

Очень полезная статья в дополнение к видеокурсам по разработке на платформе 7.6: Отладка серверного кода

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