Вопрос

Считать данные из таблицы Contact

Добрый день! Подскажите, пожалуйста, каким образом необходимо корректно формировать 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 в последних версиях.

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