Вопрос

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

Изучили ряд тем на сообществе по данному вопросу и попробовали воспроизвести кейс из данной темы:

https://community.terrasoft.ru/questions/anonimnaa-autentifikacia-vnesn…

Сделали всё в точности как описано в примере, включая настройку web-конфигов. 

Сервис:

namespace Terrasoft.Configuration
{
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Data;
 using System.Linq;
 using System.Security;
 using System.ServiceModel;
 using System.ServiceModel.Web;
 using System.ServiceModel.Activation;
 using System.Web;
 using Terrasoft;
 using Terrasoft.Common;
 using Terrasoft.Common.Json;
 using Terrasoft.Core;
 using Terrasoft.Core.DB;
 using Terrasoft.Core.Entities;
 using Terrasoft.Core.Store;
 using Newtonsoft.Json;
 
 using Terrasoft.Web.Common;
 
    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    public class UsrGreetingService : BaseService //,System.Web.SessionState.IReadOnlySessionState
    {
 
        [OperationContract]
        [WebInvoke(Method = "GET", UriTemplate = "Hello", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public string TestHello()
        {
            return "Hello!!!!!!!!!!!!!!!!!";
        }
 
 
        [OperationContract]
        [WebInvoke(Method = "GET", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Xml)]
        public string TestHelloXml()
        {
            return "Hello!!!!!!!!!!!!!!!!!";
        }
 
        [OperationContract]
        [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json)]
        public string TestPostJson()
        {
            return "Hello!!!!!!!!!!!!!!!!!";
        }
 
 
 
 
 //       private UserConnection _userConnection;
  /// <summary>
  /// </summary>
// private UserConnection UserConnection {
//  get {
//   return _userConnection ?? (_userConnection = HttpContext.Current.Session["UserConnection"] as UserConnection);
 //  }
// }
    }
}

 

В результате попробовали отправить запрос через POSTMAN

1) Если указать метод GET без авторизационных Cookie, то всё работает

Как пример можно получить результат запроса по ссылке:

http://93.188.21.108:2022/0/ServiceModel/UsrGreetingService.svc/Hello

 

2) Указываем метод POST без авторизационных Cookie, то получаем 403:

 

 

Если же добавить к запросу(метод POST) авторизационные Cookie, то всё работает...

Коллеги, прошу подсказать, что именно делаем не так?

 

У меня такой же вопрос

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

Добрый день, 

Проверьте включена ли на сайте CSRF-защита. В внешнем и внутреннем Web.config есть атрибут UseCsrfToken, содержит значение true то можно поступить следующим образом: 

1. Изменить значение UseCsrfToken в Web.config и WebApp/Web.config на 

<add key="UseCsrfToken" value="false" />

2. В хедере запроса отправлять Csrf-токен. Следующим образов (в случае безавторизационного сервиса, авторизацитонные куки можно не отправлять):

Tsopa,

Спасибо большое! Решили проблему получением и отправкой

авторизацитонных куков!

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день!

Реализую возможность добавить информацию о звонке в BPM через OData.

Что я делаю: POST запрос с Content-Type: application/json;odata=verbose;type=entry на https://phonetcomua.bpmonline.com/0/ServiceModel/EntityDataService.svc/CallCollection

JSON имеет такой вид:

{
    "CalledId": "+380990056970",
    "CallerId": "+380990056960",
    "Duration": 400,
    "TalkTime": 299,
    "Direction": {
          "__metadata":{"uri":"??????"}
    },
    "Contact": {
        "__metadata":{"uri":"ContactCollection(guid'97d39836-b242-462a-b375-9daa32e553e4')"}
    }
   
}

Непонятно как указать URI с guid для Direction и Result свойств.

Я знаю возможные значения guid для enum-a CallDirection, но я не знаю как правильно ссылаться на этот объект при добавлении звонка.

У меня такой же вопрос

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

Вопрос снят. Почему то не догадался попробовать CallDirectionCollection.

Почему добавленные через OData звонки не отображаются в разделе Звонки.
Во вкладке История у конктакта краткая информация о звонке отображается.
Если перейти по https://phonetcomua.bpmonline.com/0/Nui/ViewModule.aspx#CardModuleV2/Ca… информация о звонке доступна

"Developer2" написал:Если перейти по https://phonetcomua.bpmonline.com/0/Nui/ViewModule.aspx#CardModuleV2/Cal... информация о звонке доступна

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

"Developer2" написал:Почему добавленные через OData звонки не отображаются в разделе Звонки.
Во вкладке История у конктакта краткая информация о звонке отображается.

Сравните записи в базе напрямую, полученную через одата и обычную, разницу и увидите... может типа какого не хватает заполненного
Если ондеманд, поищите тут был sql executer для выполнения запросов

"Александр Кудряшов" написал:Если ондеманд, поищите тут был sql executer для выполнения запросов

Александр подскажи пожалуйста где тут поискать?

"Власов Михаил Викторович" написал:

Александр подскажи пожалуйста где тут поискать?


"sqlexecuterpage" вот тут

"Александр Кудряшов" написал:
Developer2 пишет:

Почему добавленные через OData звонки не отображаются в разделе Звонки.
Во вкладке История у конктакта краткая информация о звонке отображается.

Сравните записи в базе напрямую, полученную через одата и обычную, разницу и увидите... может типа какого не хватает заполненного
Если ондеманд, поищите тут был sql executer для выполнения запросов

Спасибо за ответ!

Разобрался. Все прикреплялось. Я просто на странице не ту вкладку смотрел. Нужно было на Список переключить.

У меня еще один вопрос. На странице https://academy.terrasoft.ua/documents/customer-center/7-8-0/zapis-i-pr… сказано, что можно прослушивать звонки.
Так вот, я пока через интерфейс пробовал добавить ссылку с записью на разговор, она добавляется, но кнопка прослушать не появляется. Возможно какая-то настройка отключена, поскольку в примечании говорится

Возможность прослушать аудиозапись звонка будет доступна при выполнении персональных настроек.

Можете подсказать будет ли работать через ссылку на аудиозапись или это фича только для Oktell и Webitell?

"Developer2" написал:Можете подсказать будет ли работать через ссылку на аудиозапись или это фича только для Oktell и Webitell

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

"Александр Кудряшов" написал:
Developer2 пишет:

Можете подсказать будет ли работать через ссылку на аудиозапись или это фича только для Oktell и Webitell

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

При интеграции с Мегапланом именно так и делали. Вставляли ссылку и затем через chrome extension изменяли страницу.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Привет.
Есть POST сервис на C#, который принимает и возвращает json.
Появилась идея, чтоб не регистрировать этот сервис в bpmonline запускать его через бизнес процесс.
Все нормально работает, но вот как передать в БП json тело и получить некий json обратно?
Пока удалось только передать параметры в Url.

У меня такой же вопрос

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

Добрый день,
На данный момент в сервисе ProcessEngineService нет такого метода, который бы позволял передавать параметры из тела POST запроса. Есть похожий метод ExecuteProcessWithResultPost но он устанавливает параметры процесса только из URL.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день!

Подскажите, пожалуйста, как в функции SaveChanges, а точнее в BaseDBEdit.Dataset.Post() определяется набор полей которые надо обновить? Почему-то измененное поле сохраняется не всегда...

Заранее благодарен.

У меня такой же вопрос

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

"AlexLS" написал:как...определяется набор полей которые надо обновить

никак. Поля, которые Enabled в датасете, сохраняются в БД. Конечно, если поля корректно настроены и для них нормально формируется элемент в selectQuery. Например, если поле получается подзапросом, его изменения просто так не сохранятся.

см также http://www.community.terrasoft.ru/blogs/8933

ПС.

"AlexLS" написал:Почему-то измененное поле сохраняется не всегда...

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

"AlexLS" написал:Почему-то измененное поле сохраняется не всегда...

Александр, это же подход менеджера, но не разработчика :)
Профайлер в руки и упорным анализом логов познаем закономерность.
Кстати эффект "не сохраняется" может быть из-за криво написанных обработчиков событий на датасете или карточке - типа смены значений полей при изменении других... смены не видно глазами, а она фоном происходит в датасете, ну и при сохранении уже в таблицы попадает

"Андросов Дмитрий" написал:когда сохраняется, а когда - нет?

Дмитрий, спасибо за ответ! Пытаюсь сообразить, но пока понял что при инсерте сохраняется, а пр апдейте нет. Непосредственно перед постом, в

function SaveChanges(BaseDBEdit, Window) {
...
var PostResult = BaseDBEdit.Dataset.Post();
...

, значения следующие:

Dataset.DataFields('PhoneNumber').IsReadOnly = false;
Dataset.DataFields('PhoneNumber').ValueIsChanged = true;
Dataset.DataFields('PhoneNumber').IsEnabled = true;
Dataset.SelectQuery.Columns.ItemsByAlias('PhoneNumber').IsEnabled = true;

Что-то еще забыл указать? (да, сразу после поста значения НЕ изменились!)

"Андросов Дмитрий" написал:Проверьте профайлером, идет ли у вас апдейт таблицы в тех случаях, когда не сохраняется.

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

Проверьте в датасете - быть может у вас Updatequery не генерируется автоматом?

"Олейник Дмитрий" написал:Проверьте в датасете - быть может у вас Updatequery не генерируется автоматом?

Наверно тогда бы другие поля не сохранялись? А так обновляются все поля кроме указанного текстового поля. Ну в датасете все прописано нормально.

Добрый день!

Прошу уточнить, какое у Вас состояние датасета перед "постом":

BaseDBEdit.Dataset.State

Также, посмотрите, какой UpdateQuery у Вас генерируется перед изменением значения, а какой - после.
Также, посмотрите запрос в профайлере SQL.

"Безродный Андрей" написал:Прошу уточнить, какое у Вас состояние датасета перед "постом":

Состояние где "надёжнее" проверить? В "OnDatasetBeforePost" датасета или в скрипте карточки в "dlDataOnDatasetBeforePost" (аналогичный вопрос с after)?

"Безродный Андрей" написал:Прошу уточнить, какое у Вас состояние датасета перед "постом":

BaseDBEdit.Dataset.State

В ProcessBaseDBEditOKOnClick -> SaveChangesWithCheck -> SaveChanges

	var PostResult = BaseDBEdit.Dataset.Post();

смотрю:
перед: BaseDBEdit.Dataset.State 2 Number
после: BaseDBEdit.Dataset.State 1 Number

Запрос:

exec sp_executesql N'UPDATE [dbo].[vw_SCall]
	SET [ModifiedOn] = getdate(),
	[ModifiedByID] = ''{9149E4AB-B8E2-491A-A2B1-AA344021DAF8}'',
	[Description] = @P1
WHERE([vw_SCall].[ID] = @P2)',N'@P1 varbinary(8000),@P2 uniqueidentifier',NULL,'835BBD40-EAE4-4139-8466-93A00156C624'

"Безродный Андрей" написал:какой UpdateQuery у Вас генерируется перед изменением значения

BaseDBEdit.Dataset.UpdateQuery.SQLText
UPDATE [dbo].[vw_SCall]
	SET [ModifiedOn] = NULL,
	[ModifiedByID] = NULL
WHERE([vw_SCall].[ID] = :ID)

не смотря на то что:

Dataset.DataFields('PhoneNumber').ValueIsChanged = true
BaseDBEdit.Dataset.DataFields('PhoneNumber').ValueIsChanged = true

Под пользователем ограниченным выполняем изменение? Судя по wv_SCall

Советую посмотреть триггер tr_vw_SCall_IU (где-то так должен называться) на этой вьюшке, который отвечает за update непосредственно таблицы, по результату update вьюхи. Там с этим полем PhoneNumber все в порядке - может пропущено оно где в запросах?

"Александр Кудряшов" написал:посмотреть триггер tr_vw_SCall_IU

посмотрел [dbo].[tr_vw_SCall_IU]
есть строка  [P].[PhoneNumber] = [I].[PhoneNumber],  
у меня мысли были что из-за того что поле где-то принимает  IsReadOnly = true (а я меняю это значение если вставка необходима), может как-то влияет на строящийся запрос вставки, но как это подтвердить не знаю и как поправить тоже не понимаю...

а галочка в selectQuery под названием "Всегда выбирать в запросе" стоит? :cool:

"Андросов Дмитрий" написал:

а галочка в selectQuery под названием "Всегда выбирать в запросе" стоит? :cool:


А зачем она, если поле в SELECT'е выбрано? Или тут тоже есть "секрет"?

Если она не стоит и поле нигде не отображается, оно не попадает в запрос. По аналогии можно предположить (я не знаю как на самом деле), что если поле при создании экземпляра датасета имеет свойство Только на чтение, оно не попадает в автоматически формируемый UpdateQuery. Т.к. UpdateQuery формируется на основе SelectQuery, можно предположить, что эта галочка добавит поле в апдейт, игнорируя признак Только на чтение. Попробуйте)
Правильно ли я понял, что в самом датасете (сервисе) у вас стоит свойство Только на чтение для этого поля, а потом в скрипте вы его меняете? Если так, то попробуйте установить его в False, а потом в скрипте менять по необходимости.

А я бы предложил вообще без всяких хитрых изменений попробовать в совершенно отвлеченном месте получить экземпляр этого датасета, отключить ему эвенты и попробовать сделать Open(), Edit(), потом поменять значение поля нужного и Post(). Потом посмотреть все ли поменялось. Если ок, искать причины в том месте, где возникает проблема - карточка, события на датасете и т.д

"Андросов Дмитрий" написал:Правильно ли я понял, что в самом датасете (сервисе) у вас стоит свойство Только на чтение для этого поля, а потом в скрипте вы его меняете?

Дмитрий, спасибо! В датасете галка не стоит, а устанавливается в true на OnPrepare, затем на кнопке OK на всякий случай меняю это свойство на false.

"Александр Кудряшов" написал:Потом посмотреть все ли поменялось

Александр, спасибо! Видимо так и придется пробовать!

Итак, если кому-то интересно: :biggrin:

на  OnDatasetBeforeEdit нельзя вешать обновление данных

"AlexLS" написал:на  OnDatasetBeforeEdit нельзя вешать обновление данных

конечно, т.к. это событие которое срабатывает перед переводом датасета в состояние редактирования (Dataset.Edit())

"Андросов Дмитрий" написал:конечно, т.к. это событие которое срабатывает перед переводом датасета в состояние редактирования (Dataset.Edit())

Дмитрий, если б Вы это "конечно" сказали тут было бы круто!!!

"AlexLS" написал:если б

если б вы о OnDatasetBeforeEdit сказали бы раньше, чем тут было бы тоже весьма кстати

Войдите или зарегистрируйтесь, чтобы комментировать
Публикация

Здравствуй, читатель. Давно мы не встречались с тобой.
Хочу поведать тебе об одной ошибке, выявление причины которой у меня заняло немало времени и дабы не наступать на эти грабли снова, внимай же голосу моему.

Если ты по некой неосторожности датафилду с типом Float присвоишь значение NaN, то система тебе ничего не скажет плохого. Однако, когда ты скажешь датасету: "Post!", система встретит тебя ошибкой вида:

TSObjectLibrary.DBDataset: Error posting record. Original error message: The incoming tabular data stream (TDS) remote procedure call (RPC) protocol stream is incorrect. Parameter 20 (""): The supplied value is not a valid instance of data type float. Check the source data for invalid values. An example of an invalid value is data of numeric type with scale greater than precision

Эта ошибка возникает на стороне клиента, так что в профайлере ты ничего не увидешь.

Если ты, читатель, думаешь, что получить значение NaN очень сложно, то это не так. Достаточно написать:

var a = Dataset.Values('Subject');
var b = Dataset.Values('Divisor');
if (b != 0) {
   Dataset.Values('Result') = a / b;
};

Уважаемый написавший сей код не затруднил себя проверить, что a и b неравны null и в итоге при некоторых обстоятельствах (когда второй операнд = null) получил NaN. (опытный читатель воскликнет, что надо было использовать ValAsFloat вместо Values).

Спасибо за внимание и до новых встреч в эфире.

Поделиться

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

"Встреча с неведомым" и как ее избежать))
по идее ругаться система должна была еще при попытке присвоения NaN в тот самый датафилд - может стоит добавить отработку данного события этаким хитрым образом на уровень самого объекта Dataset, чтобы не ловить потом хитрые сообщения?

Нифига не понятно, но стиль - прекрасен!

"Репко Артём" написал:(опытный читатель воскликнет, что надо было использовать ValAsFloat вместо Values).

Я так понимаю, ValAsFloat нужно только в первых двух строчках? ;).

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

"Лабьяк Олег Игоревич" написал:Я так понимаю, ValAsFloat нужно только в первых двух строчках? ;).

Да, в последней строчке необязательно, хотя и не помешает.

При использовании метода ValAsFloat() нужно быть уверенным что в DataField имеет тип Integer или Float.

"Кривонос Максим" написал:При использовании метода ValAsFloat() нужно быть уверенным что в DataField имеет тип Integer или Float.

Более того, нужно быть увереным, что переменная Dataset является объектом, реализующим интерфейс IDataset.

Артём, +1 ))).

Олег Лабьяк,
разработчик,
3-я линия Службы поддержки Terrasoft.

Я был не прав, тип DataField'a не обязательно должен быть Integer или Float, главное чтоб его значение было подходящим.

Воспроизвел ситуацию, но сообщение появилось немного другое:
TSObjectLibrary.DBDataset: Error posting record. Original error message: A floating point exception occurred in the user process. Current transaction is canceled

Кстати, для воспроизведения хватило бы написать:

Dataset.Values('Result') = NaN;

А в текущем примере если немного изменить, то ошибка бы не появилась:

var a = Dataset.Values('Subject');
var b = Dataset.Values('Divisor');
if (b) {
   Dataset.Values('Result') = a / b;
};

Думаю какую проверку нужно добавить в ядро. Если передают NaN конвертировать в null?

"Александр Кравчук" написал:Dataset.Values('Result') = NaN;

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

"Александр Кравчук" написал:Думаю какую проверку нужно добавить в ядро. Если передают NaN конвертировать в null?

Я бы лучше исключение генерировал. Вряд ли человек, написавший Dataset.Values('a') = 5 + a / b (где b равно null), ожидает в результате увидеть null в поле.

"Репко Артём" написал:Я бы лучше исключение генерировал.

Согласен, наверное так и сделаю.

Дякую Артем!
Ніколи не знаєш, коли така інформація стане корисною. І ось цей час настав.

Войдите или зарегистрируйтесь, чтобы комментировать
Вопрос

Добрый день!

Имеется следующий код:

       //...
var SelectQuery = Services.GetNewItemByUSI('sq_ReelInBlock');
ApplySelectQueryFilter(SelectQuery, 'BlockID', BlockID, true);
ApplySelectQueryFilter(SelectQuery, 'ReelTypeID', ReelTypeCommercial, true);
var ds_CurReelsInBlock = SelectQuery.Open();
        //...

затем идет обработка этого датасета и новые данные записываются в MemoDataset.
Мне необходимо до обработки данных добавить еще один элемент в датасет ds_CurReelsInBlock. Если применить Append и Post, будет ли новая запись датасета занесена в таблицу БД? Мне нужно этого избежать.

Заранее благодарю!

У меня такой же вопрос

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

Будет. Можно подвязаться на событие OnBeforePost и запрещать пост. Но как по мне нужно делать совсем по другому. Опишите задачу, может что-нибуть придумаем.

Войдите или зарегистрируйтесь, чтобы комментировать