Добрый день!

При сохранении записи в детали средства связи возникают странные ошибки. Метод сохранения вызывает BatchQuery для Update сохраняемой записи. 

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

Однако при исполнении данного скрипта возникает следующая ошибка:

Конфликт инструкции DELETE с ограничением REFERENCE "FK4eIKa4vC33vluosjyKmFjgDPk3o". Конфликт произошел в базе данных "ArdshinBank7102-2", таблица "dbo.AppFormCommunication", column 'ContactCommunicationId'. ↵Выполнение данной инструкции было прервано."

Непонятно, каким образом возникло удаление, если выполнялся скрипт на модификацию записи.

 

Посмотрел событийные процессы объекта ContactCommunication, нигде нет удаления.

Подскажите, в какую сторону смотреть для решения ошибки.

 

Нравится

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

вот вам скрипт поиска зависимостей по ключу

 

SELECT
    C.CONSTRAINT_NAME,
    PK.TABLE_NAME,
    CCU.COLUMN_NAME,
    FK.TABLE_NAME,
    CU.COLUMN_NAME,
    C.UPDATE_RULE,
    C.DELETE_RULE
FROM
    INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C INNER JOIN
    INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME INNER JOIN
    INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME INNER JOIN
    INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME INNER JOIN
    INFORMATION_SCHEMA.CONSTRAINT_COLUMN_USAGE CCU ON PK.CONSTRAINT_NAME = CCU.CONSTRAINT_NAME
WHERE
    FK.CONSTRAINT_TYPE = 'FOREIGN KEY' AND c.[CONSTRAINT_NAME] like '%KEY'
ORDER BY
    PK.TABLE_NAME, 
    FK.TABLE_NAME;

Вместо '%Key' -> '%FK4eIKa4vC33vluosjyKmFjgDPk3o' и смотрите какая колонка от какой зависит.

И насколько я понимаю update = delete->insert в sql

Так откуда зависимость, как раз понятно из сообщения: в другой таблице AppFormCommunication есть ссылка ContactCommunicationId. Но почему при изменении ContactCommunication связь сломалось — надо разбираться.

Update — это не Delete с Insert. Ведь при переименовании какого-нибудь контакта система не ругается на связи с ним.

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

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

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

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

При переносе с одного стенда на другой возникла проблема актуализации переводов.

А именно, перевел нужные названия и залил в данные SysTranslation. 

При переносе данные поставились (в бд новые значения), но по факту под разной локализацией значения старые.

Раскопал, что значения берутся по факту для справочников из таблиц типа SYSНазвание_ОбъектаLcz. Тут как раз старые значения, как в них обновить?

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

В переводах кнопка "актуализация данных" не помогает.

Нравится

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

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

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

Таблицы типы SysОбъектLcz нельзя привязать к пакету, т.к. их нет в конфигурации. 

Может, они подхватятся при синхронизации записей основного справочника?

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

можете пож-ста поподробнее.

Видимо, после изменения наполнения справочника его не переносили пакетами на другую базу.

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

Выполнил загрузку пакета по инструкции: 

https://academy.terrasoft.ru/documents/technic-sdk/7-12/zagruzka-paketo…

Командой: 

C:\bpmonline7.9.2\Terrasoft.WebApp\DesktopBin\WorkspaceConsole\Terrasoft.Tools.WorkspaceConsole.exe -packageName=userPackage -workspaceName=Default -operation=InstallFromRepository -sourcePath=C:\SavedPackages -destinationPath=C:\TempPackages -skipConstraints=false -skipValidateActions=true -regenerateSchemaSources=true -updateDBStructure=true -updateSystemDBStructure=true -installPackageSqlScript=true -installPackageData=false -continueIfError=true -logPath=C:\Log

Где параметр "-packageName=userPackage" заменил на собственное название пакета.

Вместе с моим пакетом, подтянулись все другие пакеты, включая базовые. Сейчас стоит вопрос о том, как можно(если можно) вернуть Bpm  в исходное состояние(до загрузки нового пакета), а так же стоит вопрос, по какой причине такое могло произойти, если на параметр "-packageName" должен устанавливать только указанный пакет? 

Нравится

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

Можно предположить, что остальные пакеты поставились от того, что нужный от них зависел. Проще будет откатить из бекапа.

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

Привет всем!

Система не получает сообщения из почтового ящика( MS Exchange) до тех пор пока в систему не войдет Supervisor, только после этого система начинает прием и обработку сообщений.

 

Нравится

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

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

Для исправления данного кейса необходимо установить для пула приложений IIS, на котором работает приложение, Idle Timeout = 0

1. Настроить автоматический мониторинг Loader'a и приложения, ниже варианты:

  • С помощью бесплатного сервиса мониторинга https://uptimerobot.com/ настроить автоматический мониторинг c периодичностью 5-10 минут - наиболее быстрый путь
  • С помощью автоматического запуска скрипта мониторинга приложения. Шаблон скрипта PowerShell в приложении Ping.ps1, в нем необходимо изменить адрес приложения. После этого, нужно запланировать выполнение этого скрипта через планировщик Windows c периодичностью 5-10 минут. Автоматический запуск можно настроить по инструкции http://windowsnotes.ru/powershell-2/zapusk-powershell-skripta-po-raspisaniyu/.

 

2. Настроить автоматический запуск SQL-скрипта очистки \ перезапуска зависших заданий, скрипт в приложении ResetErrorQuartzTriggers.sql - с периодичностью 30 минут

  • Настроить автоматический запуск задания MSSQL, выполняющего этот скрипт - наиболее простой способ

Скрипты можно скачать по данной ссылке:https://dropmefiles.com/QhuAh

Shevchenko Andrey,

добрый день! скрипты выложите еще раз.

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

Выше в моем комментарии названия файлов являются кликабельными и вы можете скачать скрипты просто нажав на них.

Shevchenko Andrey,

не скачиваются скрипты. На dropmefiles пишет что файлы удалены, по самому скрипту - web страница недоступна

Ольга Кондратьева,

Добрый день! Можете скачать по ссылке - 

https://www.dropbox.com/sh/re9v0093hflrmuf/AADQ1_2KNUQgLJS2DnkB0Gyia?dl…

Подскажите, в какой версии исправили данную багу? В 7.12.2.935 нужно настраивать скрипт ResetErrorQuartzTrigger?

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

При попытке создать исходный код в пакете, появляется следующая запись, добавить получается только процесс...

Нравится

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

В пакеты, которые установлены из marketplace или из архива, или базовые пакеты, добавлять схемы нельзя. Попробуйте добавить исходный код в пользовательский пакет.

 

Большое спасибо!

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

Оба пользователя имеют одинаковый доступ к очереди.

Очередь настроена так:

Активность:

- Категория: Email

- Тип сообщения: Входящее

- Статус: Не начата

 

Проблема:

1) в списке Единого окна отображается разное кол-во записей. У одного пользователя не видны некоторые записи. Например у Supervisor 10 входящих, а у Artem 8 входящих, 2 записи должны отображаться, но их нет.

2) в списке Единого окна есть записи у которых Статус = Завершена, хотя в фильтре установлено отображать только Не начатые.

 

Как это окно работает, почему эти проблемы появились?

Нравится

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

Здравствуйте, Дмитрий!

По порядку:

1) В Едином окне будут отображаться записи, на которые есть доступ у  пользователя. Проверьте права доступа на запись. 

Так же запись должна быть в Едином Окне в статусе "Не обработана" или "В работе", тогда она будет отображаться.

http://prntscr.com/k45uj4

2) Вы можете построить в разделе, по которому строится "Единое Окно", фильтр из очереди, чтобы убедиться в том какие записи попадут в очередь. По данному вопросу необходимо увидеть какие у Вас выполнены настройки в очереди. Возможно у Вас стоит условие фильтрации "ИЛИ", вместо "И"

 

Гриценко Игорь пишет:

Так же запись должна быть в Едином Окне в статусе "Не обработана" или "В работе", тогда она будет отображаться

Это неправильно. Поскольку отсутствует возможность настроить очередь. Я не знаю как, но там появились записи, которые не соответствуют фильтру и в статусе В работе или Не завершена. Такого не должно быть, это нонсенс. Человек ожидает - настроил фильтр очереди - и в этом списке четко именно те записи, которые удовлетворяют фильтру. Я считаю это баг, или вы недостаточно проработали этот вопрос. 

Гриценко Игорь пишет:

Вы можете построить в разделе, по которому строится "Единое Окно", фильтр из очереди, чтобы убедиться в том какие записи попадут в очередь

Эта опция не работает! сколько угодно строишь очередь, меняешь фильтр, все одно - записи не соответствуют фильтру. Там какой-то баг дополнительно. У меня все правильно с фильтрами, это самое простое что можно сделать, фильтр "И". Права раздать элементарно, да и при чем тут права, если записи, которые отображаются - не соответствуют фильтру, там присутствуют кроме фильтра - дополнительные записи. 

Т.е. вывод - этот баг, или недоработка, что в очереди присутствуют записи по фильтру + записи В работе или Не обработана. Вопрос решился только путем удаления старой очереди и создания НОВОЙ, что исключает возможность переноса очереди посредством Данных. это БАГ. Предлагаю рассмотреть этот вопрос и исправить в новых версиях, чтобы записи были только в соответсвии с фильтром, или добавить дополнительный фильтр, которым можно включать выключать фильтр непосредственно очередей (статусы и т.д. ) поскольку реально этими статусами с помощью очереди управлять нельзя.

Добрый день, Дмитрий

Напишите на почту тех. поддержки - support@terrasoft.ru по данной проблеме.

Так же необходим будет кейс воспроизведения данной ошибки на базовой версии(без доработок) bpm'online (https://www.terrasoft.ru/trial?product=service).

Гриценко Игорь,

хорошо спасибо. 

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

Добрый вечер, коллеги. Такой вопрос: имеется раздел контактов и раздел профессий. Контакт содержит ФИО и номер телефона. При чем в гриде контактов - все номера телефонов идут как гиперссылка, при нажатии на которую идет звонок на этот номер телефона. В грид раздела "контакт в профессии" добавлен столбец "контакт.номер_телефона", но он уже отображается как обычная строка. Каким образом его можно сделать также гиперссылкой как и в разделе контакты?

Нравится

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

Вам в CtiLinkColumnUtility, там прописываются какие колонки в объекте считать гиперссылкой для вызовов.

Ну или переопределить addColumnLink в секции, отсеять по колонке и навешивать обработчик самостоятельно для колонки с телефоном

Вам в CtiLinkColumnUtility, там прописываются какие колонки в объекте считать гиперссылкой для вызовов.

Ну или переопределить addColumnLink в секции, отсеять по колонке и навешивать обработчик самостоятельно для колонки с телефоном

Спасибо! Все получилось!

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

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

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

Задача следующая: 

Необходимо рядом с именем вкладки "Файлы" выводить counter связанных вложений. Т.е. выглядеть это должно примерно так: "Файлы (3)".

Как посчитать количество вложений - ясно. Но как изменять имя вкладки?

Добавил в init() следующий код:

var tabsCollection = this.get("TabsCollection");
this.set("Resources.Strings.UsrFilesCounterCaption" , this.get("UsrFileCounter"));
var fileCount = this.get("Resources.Strings.UsrFilesCounterCaption");
tabsCollection.collection.items[3].values.Caption  = fileCount;

Но на странице ничего не изменилось...

Нравится

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

Добрый день, Павел!

Вам необходимо менять модель, а не values, т.е. примерно так:

tabsCollection.collection.items[3].model.attributes.Caption = fileCount;

Или как еще один вариант:

tabsCollection.collection.items[3].set("Caption", fileCount);

 

Как вариант, найти определение в diff нужной вкладки, в values дописать

"caption": {"bintTo": "MyTabCaption"}

Где MyTabCaption - виртуальный аттрибут, определённый в attributes. В него и устанавливайте значения.

Добрый день, Павел!

Вам необходимо менять модель, а не values, т.е. примерно так:

tabsCollection.collection.items[3].model.attributes.Caption = fileCount;

Или как еще один вариант:

tabsCollection.collection.items[3].set("Caption", fileCount);

 

Спасибо!Вот такая функция получилась:

initUsrFileCounterCaption: function() {
					var fileCount = null;
					var tabsCollection = this.get("TabsCollection");
					var recordId = this.get("Id");
					if (recordId && recordId !== null && !this.Ext.isArray(recordId)) {
						var esq = Ext.create("Terrasoft.EntitySchemaQuery", {rootSchemaName: "CaseFile"});
						esq.addColumn("Id");
						esq.addColumn("Case");
						esq.filters.add("CaseFilter", Terrasoft.createColumnFilterWithParameter(Terrasoft.ComparisonType.EQUAL, "Case.Id", recordId));
 
						esq.getEntityCollection(function(result) {
							if (result.success) {
								var collection = result.collection;
								if (collection) {
									fileCount = (this.get("Resources.Strings.UsrFilesCounterCaption") + " (" + collection.getCount() +  ") ");
									tabsCollection.collection.items[3].set("Caption", fileCount);
								}
							}
						}, this);
					} else {
						fileCount = (this.get("Resources.Strings.UsrFilesCounterCaption") + " (0) ");
						tabsCollection.collection.items[3].set("Caption", fileCount);
					}
			},

 

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

Добрый день! Столкнулся со следующей проблемой:

1) Захожу в Tools -> Configuration -> Schemas:All

2) Кликаю по кнопке "Add"

3) Выбираю "Source code"

4) Появляется сообщение:

> An error occurred in bpm'online. We apologize for the inconvenience.

> Back to Previous Page.

> Please notify the bpm'online support about this error.

> We guarantee your confidentiality and anonymity.



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

Какова может быть причина данной ошибки?

Нравится

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

Добрый день!



Пришлите, пожалуйста, скриншоты из консоли. (Нажмите F12 - Перейдите на вкладку Консоль - Воспроизведите ошибку)

Анна, скрин консоли прикрепил

engineer7,

Есть множество возможных причин появления подобной ошибки.

Достоверно определить причину возникновения 500 ошибки возможно, изучив логи сервера. Советую Вам проверить настройки сайта в IIS, а так же права на папки или файлы.



Если ошибка будет продолжать воспроизводится, советую Вам отправить подробное описание кейса со скриншотами поведения на почтовый ящик support@bpmonline.com

В логах нашел более подробное описание: 

Exception Message: Value for argument "uid" must be specified.

Exception Type: Terrasoft.Common.ArgumentNullOrEmptyException

Exception Source: Terrasoft.Common



Exception Stack Trace:

   at Terrasoft.Common.ValidateUtilities.CheckArgumentEmpty(Guid source, String argumentName)

   at Terrasoft.Core.Packages.PackageIdentifierMapper.GetIdByUId(Guid uid, Guid workspaceId)

   at Terrasoft.Core.SchemaManager`1.CreateSchemaItem(Guid packageUId, String name, TSchemaManagerSchema parentSchema, Boolean extendParent, UserConnection userConnection)

   at Terrasoft.Core.SchemaManager`1.CreateDesignSchema(UserConnection userConnection, Guid parentSchemaUId, Guid packageUId, Boolean extendParent)

   at Terrasoft.Core.SchemaManager`1.Terrasoft.Core.ISchemaManager.CreateDesignSchema(UserConnection userConnection, Guid parentSchemaUId, Guid packageUId, Boolean extendParent)

   at Terrasoft.WebApp.WorkspaceExplorerModule.CreateSchema(String managerName, Guid packageUId, IDictionary`2 extraParameters)

   at Terrasoft.WebApp.WorkspaceExplorerModule.OnTreeAddMenuItemClick(Object sender, AjaxEventArgs e)

   at Terrasoft.UI.WebControls.Controls.ComponentAjaxEvent.OnEvent(Object sender, AjaxEventArgs e)

   at Terrasoft.UI.WebControls.Controls.Observable.FireAsyncEvent(String eventName, ParameterCollection extraParams)

   at Terrasoft.UI.WebControls.Controls.ScriptManager.RaisePostBackEvent(String eventArgument)

   at Terrasoft.UI.WebControls.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument)

   at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)



Form:

    submitAjaxEventConfig: {"config":{"viewStateMode":"include","extraParams":{"tag":"","ManagerName":"SourceCodeSchemaManager"}}}

    __EVENTTARGET: ScriptManager

    __EVENTARGUMENT: AddSourceCodeSchemaMenuItem|event|Click

    __VIEWSTATEFIELDCOUNT: 37

    __VIEWSTATE0:

engineer7,

для детального анализа Вашего кейса необходим доступ к сайту с ошибкой. Направьте нам его, пожалуйста, на почтовый ящик support@bpmonline.com (параметры для входа/удаленного подключения или обезличенный бекап БД)

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

Добрый день! Подскажите, пожалуйста, каким образом необходимо корректно формировать SelectRequest, для того что бы получить всю таблицу из бд?



Нашел информацию по этой ссылке:https://academy.terrasoft.ru/documents/technic-sdk/7-12/dataservice-cht…

Тут именно тот код:

//------------------------------------------------------------------------------

// Экземпляр класса запроса.
var selectQuery = new SelectQuery()
{
    // Название корневой схемы.
    RootSchemaName = "Contact",
    // Коллекция колонок запроса.
    Columns = new SelectQueryColumns()
};
// Выражение, задающее тип колонки [[ФИО].
var columnExpressionName = new ColumnExpression()
{
    // Тип выражения — колонка схемы.
    ExpressionType = EntitySchemaQueryExpressionType.SchemaColumn,
    // Путь к колонке.
    ColumnPath = "Name"
};
// Конфигурирование колонки [Name]. 
var selectQueryColumnName = new SelectQueryColumn()
{
    //Заголовок.
    Caption = "ФИО",
    // Направление сортировки — по возрастанию.
    OrderDirection = OrderDirection.Ascending,
    // Позиция порядка сортировки.
    OrderPosition = 0,
    // Выражение, задающее тип колонки.
    Expression = columnExpressionName
};
// Выражение, задающее тип колонки [Количество активностей].
var columnExpressionActivitiesCount = new ColumnExpression()
{
    // Тип выражения — вложенный запрос.
    ExpressionType = EntitySchemaQueryExpressionType.SubQuery,
    // Путь к колонке относительно корневой схемы.
    ColumnPath = "[Activity:Contact].Id",
    // Тип функции — агрегирующая.
    FunctionType = FunctionType.Aggregation,
    // Тип агрегации — количество.
    AggregationType = AggregationType.Count
};

//------------------------------------------------------------------------------

В данном случае, у меня к примеру нет заголовка "ФИО", у меня есть просто столбец "Name"("ФИО" в данном случае это есть то как будут отображаться полученные данные или это именно часть таблицы к которой я обращаюсь?)

В данном случае, авторизация к серверу проходит успешно, но при попытке считать результат выполнения запроса, выпадает ошибка:

"Exception thrown: 'System.Net.WebException' in System.dll"

 

Нравится

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

engineer7 пишет:

и ошибок он не выдает...

Защиту от CSRF атак выключили? Просто добавление токена не наблюдаю. Попробуйте до вызова 

using (var requestStream = selectRequest.GetRequestStream())

// Добавление CSRF-токена в заголовок запроса.
CookieCollection cookieCollection = AuthCookie.GetCookies(new Uri(authServiceUri));
string csrfToken = cookieCollection["BPMCSRF"].Value;
selectRequest.Headers.Add("BPMCSRF", csrfToken);

 

Указанный пример — это при работе с системой извне. Если просто в серверном коде получать данные из таблицы, см. тут.

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

Зверев Александр пишет:

Указанный пример — это при работе с системой извне. Если просто в серверном коде получать данные из таблицы, см. тут.

Если Вам действительн...

Александр, спасибо за ответ! 



В данном случае, меня интересует второй случай, когда нужно работать с удаленным сайтом по веб-сервисам, но дело в том, что сервер возвращает не 404(нет ответа) ошибку, а 403(проблемы с доступом).



Возможно такое что я не правильно заполняю конфигурирование запроса?

 

// Экземпляр класса запроса.

            var selectQuery = new SelectQuery()

            {

                // Название корневой схемы.

                RootSchemaName = "Contact",

                // Коллекция колонок запроса.

                Columns = new SelectQueryColumns()

            };



            // Выражение, задающее тип колонки [[ФИО].

            var columnExpressionName = new ColumnExpression()

            {

                // Тип выражения — колонка схемы.

                ExpressionType = EntitySchemaQueryExpressionType.SchemaColumn,

                // Путь к колонке.

                ColumnPath = "Name"

            };

            // Конфигурирование колонки [Name].

            var selectQueryColumnName = new SelectQueryColumn()

            {

                //Загловок.

                Caption = "",

                // Направление сортировки — по возрастанию.

                OrderDirection = OrderDirection.Ascending,

                // Позиция порядка сортировки.

                OrderPosition = 0,

                // Выражение, задающее тип колонки.

                Expression = columnExpressionName

            };

            // Выражение, задающее тип колонки [Количество активностей].

            var columnExpressionActivitiesCount = new ColumnExpression()

            {

                // Тип выражения — вложенный запрос.

                ExpressionType = EntitySchemaQueryExpressionType.SubQuery,

                // Путь к колонке относительно корневой схемы.

                ColumnPath = "[Activity:Contact].Id",

                // Тип функции — агрегирующая.

                FunctionType = FunctionType.Aggregation,

                // Тип агрегации — количество.

                AggregationType = AggregationType.Count

            };

            // Конфигурирование колонки [Количество активностей].

            var selectQueryColumnActivitiesCount = new SelectQueryColumn()

            {

                //Загловок.

                Caption = "",

                // Направление сортировки — по возрастанию.

                OrderDirection = OrderDirection.Ascending,

                // Позиция порядка сортировки.

                OrderPosition = 1,

                // Выражение, задающее тип колонки.

                Expression = columnExpressionActivitiesCount

            };

            // Добавление колонок в запрос.

            selectQuery.Columns.Items = new Dictionary<string, SelectQueryColumn>()

            {

                {

                    "Name",

                    selectQueryColumnName

                },

                {

                    "ActivitiesCount",

                    selectQueryColumnActivitiesCount

                }

            };

            // Сериализация экземпляра класса запроса на добавление в JSON-строку.

            var json = new JavaScriptSerializer().Serialize(selectQuery);

            // Преобразование строки JSON-объекта в массив байтов.

            byte[] jsonArray = Encoding.UTF8.GetBytes(json);

            // Создание экземпляра HTTP-запроса.

            var selectRequest = HttpWebRequest.Create(selectQueryUri) as HttpWebRequest;

            // Определение метода запроса.

            selectRequest.Method = "POST";

            // Определение типа содержимого запроса.

            selectRequest.ContentType = "application/json";

            // Добавление полученных ранее аутентификационных cookie в запрос на получение данных.

            selectRequest.CookieContainer = AuthCookie;

            // Установить длину содержимого запроса.

            selectRequest.ContentLength = jsonArray.Length;

            using (var requestStream = selectRequest.GetRequestStream())

            {

                requestStream.Write(jsonArray, 0, jsonArray.Length);

            }

            ResponseStatus status = null;

            // Получение ответа от сервера. Если аутентификация проходит успешно, в свойство AuthCookie будут

            // помещены cookie, которые могут быть использованы для последующих запросов.

            using (var response = (HttpWebResponse)selectRequest.GetResponse())

            {

                using (var reader = new StreamReader(response.GetResponseStream()))

                {

                    // Десериализация HTTP-ответа во вспомогательный объект.

                    string responseText = reader.ReadToEnd();

                    status = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<ResponseStatus>(responseText);

                }

            }

 

В данном случае, конфигурирование колонки [name], каким образом нужно заполнять поле "Caption"?

Так как по умолчанию стояла запись "ФИО", я ее удалил, так как в таблице "Contact" у меня нет данного столбца.

Так же я не очень хорошо понимаю значение выражения, задающее тип колонки (количество активностей).

Пример, по которому пытаюсь получить доступ к БД: https://academy.terrasoft.ru/documents/technic-sdk/7-12/dataservice-cht…

Если с доступом, то, возможно, не передалась кука, полученная от AuthService. Если не уверены в доработках, сначала попробуйте со скопированными без изменений примерами.

Попробовал с исходным кодом:

// ----------------------------------------------

using System;

using System.Text;

using System.IO;

using System.Net;

using System.Collections.Generic;

using Terrasoft.Nui.ServiceModel.DataContract;

using Terrasoft.Core.Entities;

using System.Web.Script.Serialization;

using Terrasoft.Common;

namespace DataServiceSelectExample

{

    class Program

    {

        // Основной URL приложения bpm'online. Необходимо заменить на пользовательский.

        private const string baseUri = @"http://url";

        // Строка запроса к методу Login сервиса AuthService.svc.

        private const string authServiceUri = baseUri + @"/ServiceModel/AuthService.svc/Login";

        // Строка пути запроса SelectQuery.

        private const string selectQueryUri = baseUri + @"/0/DataService/json/SyncReply/SelectQuery";

        // Cookie аутентификации bpm'online.

        private static CookieContainer AuthCookie = new CookieContainer();



        // Метод выполняет аутентификацию пользователя.

        // Параметры:

        // userName — имя пользователя bpm'online,

        // userPassword — пароль пользователя bpm'online.

        private static bool TryLogin(string userName, string userPassword)

        {

            // Создание экземпляра запроса к сервису аутентификации.

            var authRequest = HttpWebRequest.Create(authServiceUri) as HttpWebRequest;

            // Определение метода HTTP-запроса.

            authRequest.Method = "POST";

            // Определение типа контента запроса.

            authRequest.ContentType = "application/json";

            // Включение использования cookie в запросе.

            authRequest.CookieContainer = AuthCookie;

            // Помещение в тело запроса учетной информации пользователя.

            using (var requesrStream = authRequest.GetRequestStream())

            {

                using (var writer = new StreamWriter(requesrStream))

                {

                    writer.Write(@"{

                        ""UserName"":""" + userName + @""",

                        ""UserPassword"":""" + userPassword + @"""

                    }");

                }

            }

            // Получение ответа от сервера. Если аутентификация проходит успешно, в свойство AuthCookie будут

            // помещены cookie, которые могут быть использованы для последующих запросов.

            using (var response = (HttpWebResponse)authRequest.GetResponse())

            {

                if (AuthCookie.Count > 0)

                {

                    return true;

                }

            }

            return false;

        }

        // Главный метод приложения.

        static void Main(string[] args)

        {

            // Если выполнение аутентификации неудачно, приложение завершает работу.

            if (!TryLogin("login", "password"))

            {

                Console.WriteLine("Ошибка аутентификации!");

                return;

            }

            // Экземпляр класса запроса.

            var selectQuery = new SelectQuery()

            {

                // Название корневой схемы.

                RootSchemaName = "Contact",

                // Коллекция колонок запроса.

                Columns = new SelectQueryColumns()

            };

            // Выражение, задающее тип колонки [[ФИО].

            var columnExpressionName = new ColumnExpression()

            {

                // Тип выражения — колонка схемы.

                ExpressionType = EntitySchemaQueryExpressionType.SchemaColumn,

                // Путь к колонке.

                ColumnPath = "Name"

            };

            // Конфигурирование колонки [Name].

            var selectQueryColumnName = new SelectQueryColumn()

            {

                //Загловок.

                Caption = "ФИО",

                // Направление сортировки — по возрастанию.

                OrderDirection = OrderDirection.Ascending,

                // Позиция порядка сортировки.

                OrderPosition = 0,

                // Выражение, задающее тип колонки.

                Expression = columnExpressionName

            };

            // Выражение, задающее тип колонки [Количество активностей].

            var columnExpressionActivitiesCount = new ColumnExpression()

            {

                // Тип выражения — вложенный запрос.

                ExpressionType = EntitySchemaQueryExpressionType.SubQuery,

                // Путь к колонке относительно корневой схемы.

                ColumnPath = "[Activity:Contact].Id",

                // Тип функции — агрегирующая.

                FunctionType = FunctionType.Aggregation,

                // Тип агрегации — количество.

                AggregationType = AggregationType.Count

            };

            // Конфигурирование колонки [Количество активностей].

            var selectQueryColumnActivitiesCount = new SelectQueryColumn()

            {

                //Загловок.

                Caption = "Количество активностей",

                // Направление сортировки — по возрастанию.

                OrderDirection = OrderDirection.Ascending,

                // Позиция порядка сортировки.

                OrderPosition = 1,

                // Выражение, задающее тип колонки.

                Expression = columnExpressionActivitiesCount

            };

            // Добавление колонок в запрос.

            selectQuery.Columns.Items = new Dictionary<string, SelectQueryColumn>()

            {

                {

                    "Name",

                    selectQueryColumnName

                },

                {

                    "ActivitiesCount",

                    selectQueryColumnActivitiesCount

                }

            };

            // Сериализация экземпляра класса запроса на добавление в JSON-строку.

            var json = new JavaScriptSerializer().Serialize(selectQuery);

            // Преобразование строки JSON-объекта в массив байтов.

            byte[] jsonArray = Encoding.UTF8.GetBytes(json);

            // Создание экземпляра HTTP-запроса.

            var selectRequest = HttpWebRequest.Create(selectQueryUri) as HttpWebRequest;

            // Определение метода запроса.

            selectRequest.Method = "POST";

            // Определение типа содержимого запроса.

            selectRequest.ContentType = "application/json";

            // Добавление полученных ранее аутентификационных cookie в запрос на получение данных.

            selectRequest.CookieContainer = AuthCookie;

            // Установить длину содержимого запроса.

            selectRequest.ContentLength = jsonArray.Length;

            // Помещение JSON-объекта в содержимое запроса .

            using (var requestStream = selectRequest.GetRequestStream())

            {

                requestStream.Write(jsonArray, 0, jsonArray.Length);

            }

            // Выполнение HTTP-запроса и получение ответа от сервера.

            using (var response = (HttpWebResponse)selectRequest.GetResponse())

            {

                // Вывод ответа в консоль.

                using (StreamReader reader = new StreamReader(response.GetResponseStream()))

                {

                    Console.WriteLine(reader.ReadToEnd());

                }

            }

            // Задержка выполнения приложения.

            Console.ReadKey();

        }

    }

}

// ----------------------------------------------

На вот этом месте возникает ошибка:

// ----------------------------------------------

// Выполнение HTTP-запроса и получение ответа от сервера.

            using (var response = (HttpWebResponse)selectRequest.GetResponse())

Сложно сказать, не видя конкретных запросов и ответов на них в Fiddler.

Может, логин и пароль не подходит.

В той статье есть ссылки на скачивание готовых файлов примеров программы на C#. Возможно, с ними заработает. 

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

Это и есть код из той статьи(https://academy.terrasoft.ru/documents/technic-sdk/7-12/dataservice-cht…), единственное что я заменил, это логин и пароль. Они в свою очередь верны, так как вызывается метод tryLogin до вызова SelectRequest, и ошибок он не выдает...

engineer7 пишет:

и ошибок он не выдает...

Защиту от CSRF атак выключили? Просто добавление токена не наблюдаю. Попробуйте до вызова 

using (var requestStream = selectRequest.GetRequestStream())

// Добавление CSRF-токена в заголовок запроса.
CookieCollection cookieCollection = AuthCookie.GetCookies(new Uri(authServiceUri));
string csrfToken = cookieCollection["BPMCSRF"].Value;
selectRequest.Headers.Add("BPMCSRF", csrfToken);

 

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

Большое спасибо, вопрос решен! Проблема была именно в этом!

Видимо, пример из справки не актуализировали для поддержки CSRF в последних версиях.

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