Десктоп-клиент всё ещё популярен у пользователей Directum RX. Один из аргументов в его пользу - это неработающая заказная разработка.
Но подождите, ведь заказную разработку мы делаем сами, почему она не работает в вебе? Примерно об этом мы сейчас и поговорим.
Прежде всего имеет смысл оговорить, что всё нижесказанное действительно в первую очередь для клиентского кода, поскольку именно его выполнение отличается в вебе и десктопе. Отличие в том, что в вебе весь клиентский код выполняется на веб-сервере, а в декстопе – тут же на клиенте.
Все прикладные функции стандартного базового решения Directum RX написаны с учётом этого факта, и все платформенные методы тоже работают с его учётом. Однако сторонние библиотеки, подключаемые в Directum RX Development Studio (далее DDS), чаще всего об этой разнице не знают, поскольку она им не нужна. Поэтому к выбору сторонних библиотек также следует подходить с оглядкой.
И немного о работе с запрещёнными классами .NET. Запрещено всё, что не разрешено, а список разрешённых классов можно найти в справке. Игнорирование этих запретов всегда на совести разработчика, но если вдруг вам потребовалось использовать что-то из запрещённых классов, то и здесь лучше заранее подумать, как это будет работать в вебе.
Теперь, когда у нас есть некоторые вводные, перейдём к разбору конкретных случаев.
В нашей практике эта функциональность в подавляющем большинстве случаев работала только в десктоп-клиенте. Например, у одного заказчика вплоть до версии 3.4 для выгрузки документов использовался алгоритм следующего вида:
Запрещённые конструкции использовались на шаге 4, в частности, классы из пространства имён System.IO. На шаге 2 подключалась внешняя библиотека, которая внутри также использовала запрещённые конструкции. Использовать такие обёртки разрешено, но как уже упоминалось выше, делать это нужно с умом. На версии 3.4 заказчик захотел перевести всех своих пользователей с десктоп-клиента на веб, но столкнулся с проблемой – выгрузка документов в вебе, что называется, не завелась. Код падал с ошибкой, и вот почему:
Исправить ситуацию решили заменой алгоритма выгрузки на такой:
У этой реализации есть один нюанс: способ с экспортом ZIP-архива работает только в веб-клиенте. Старую схему с использованием System.IO можно оставить для совместимости (например, сделать в коде ветвление в зависимости от типа клиента), а можно убрать, в зависимости от того, требуется ли форсировать переход пользователей из десктоп-клиента в веб.
Также есть альтернативный вариант выгрузки документа не в локальную папку на компьютере пользователя, а в общую папку на сервере. Такую выгрузку можно реализовать в асинхронном обработчике, который по завершении своей работы пришлёт пользователю уведомление об успешной выгрузке со ссылкой на выгруженный файл.
Эта функциональность, напротив, была самой экзотической для адаптации, но в то же время самой простой. Возможность вложить в письмо приложения к документу появилась в Directum RX сравнительно недавно, в версии 3.3. До этого разработчики выкручивались примерно так:
var docs = new List<Sungero.Content.IElectronicDocument>();
foreach (var doc in documents)
{
docs.Add(doc);
if (doc.HasRelations)
docs.AddRange(doc.Relations.GetRelated(AppModule.Constants.Module.AddendumRelationName));
}
var versions = docs.Where(d => d.HasVersions).Distinct().Select(d => d.LastVersion);
var content = AppDomain.CurrentDomain.GetAssemblies().Where(a => a.FullName.Contains("Sungero.Content.Client,")).SingleOrDefault();
var helper = content.GetTypes().Single(t => t.Name == "ElectronicDocumentHelper");
var method = helper.GetMethod("SendByMail");
if (method != null)
method.Invoke(null, new object[] {versions});
И это прекрасно работало, если не учитывать, что:
После обновления на версию 3.3 заказчик решил использовать веб-клиент вместо десктопа, где и выяснилось, что приведённый кусок кода превратился в тыкву. Хорошая новость была в том, что теперь его можно было с чистой совестью удалить, потому что аналогичная функциональность появилась в стандартной разработке Directum RX.
За всё время, что существует веб-клиент Directum RX, у нас было достаточно случаев, когда пользователи не могли работать в веб-клиенте, чтобы увидеть в этом некую тенденцию. Тем удивительнее для нас оказался результат - все эти случаи удалось описать всего в двух историях выше. Мы уверены, что у вас тоже найдётся похожий кейс, а может быть, и не один. Делитесь ими в комментариях - возможно, именно ваше решение окажется полезным другим пользователям сообщества :)
Добрый день, Александра, спасибо за статью. По поводу разрешенных и запрещенных конструкций не хватает описаний, и, как следствие, нет понимания, что и в какой момент может выстрелить. Например, согласно справке, запрещено использовать new, кроме случаев, когда создается коллекция. Однако, в базовой разработке есть обратные примеры. Та же история с перехватом исключений.
Вот такой код наблюдается в тех же самых базовых решениях, и, опять же вопреки справке, исключение не кидается дальше по стеку. Хотелось бы увидеть статью на эту тему.
Смотрю справку и вижу запрещенные возможности System.IO, мне System.IO подключать как стороннюю библиотеку?
Пример 1. Сохранить содержимое файла в новую версию документа
var dfile = Dialogs.CreateInputDialog("Выберите файл");
var file = dfile.AddFileSelect("Файл", false);
// Получить содержимое файла.
var fileContent = file.Value.Content;
// Сохранить содержимое файла в новую версию документа.
using (var memory = new System.IO.MemoryStream(fileContent))
{
var document = Sungero.Content.ElectronicDocuments.Create();
document.CreateVersion();
var version = document.LastVersion;
version.AssociatedApplication = Sungero.Content.AssociatedApplications.GetByExtension("xml");
version.Body.Write(memory);
document.Save();
}
Пример 2. Получить полный путь до файла
using System.IO;
var dfile = Dialogs.CreateInputDialog("Выберите файл");
var file = dfile.AddFileSelect("Файл", false);
// Получить имя файла.
var fileName = file.Value.Name;
// Получить полный путь до файла.
string tempPath = System.IO.Path.GetTempPath();
string filePath = string.Format(@"{0}{1}",tempPath, fileName);
вообще с переходом на веб надо менять и среду разработки, ну что за контруктор формы, делаю одно, ьа а вебе другое, нужен конструктор форм не из десктопа, а из веба, плюс разделение на серверные и клиентские функции можно убирать, раз получение сущностей работает в клиентском коде в вебе, так как клиентские код выполняется на сервере. Будет новый DDS?
Артем, System.IO надо просто прописать в верхнем блоке с директивами Using, но, раз уж эти возможности такие "запрещенные" то лучше их вынести в отдельную библиотеку
Ну, а ничего, что поведение пулов у тонкого и толстого может отличаться? Из вчерашнего: после установки доработки тонкий сыплет эксепшенами в лог и пользаков не пускает. Лог толстого чист и логины идут. Понятно, что надо исправлять доработку, но сам факт: "не работает в вебе.. а давай-как я поработаю в десктопе.. о! все работает!". Ну или вот выгрузка от сервера отчета - веб кричит, что сервер недоступен. Толстяк покряхтел, и принял отчет. Вот такие вот моменты вкупе с вышеперечисленными и создают вебу репутацию "младшего брата". Не так чтобы слабоумного, но, все же, неполноценного.
Артем, интересная ситуация.
Вот тут (https://club.directum.ru/webhelp/directumrx/sds/index.html?sds_zapreshchennye_classy.htm#anchor_prochie_classy_net_framework) четко написано, что:
Запрещается использовать все классы .NET Framework, кроме разрешенных. Например, запрещается работать c:
Однако в справке (https://club.directum.ru/webhelp/directumrx/sds/index.html?om_vybor_faila_addfileselect.htm) есть примеры кода, которые изобилуют запрещенными возможностями:
Непонятно, можно ли использовать примеры из справки, если они содержат запрещенный код.
Артем, если будет использоваться та же DCS, то разделение важно, т.к. DCS работает как десктоп-клиент.
По System.IO - как ни крути, он используется. Да, нельзя. Но используется, причем довольно таки успешно.
Иван, Никто не мешает организовать свой отправщик, используя web-api, либо что-то другое. DCS - отдельный продукт и решение о механизмах интеграции принимается командой внедрения.
Добрый день.
По поводу кейса "Отправка документов по электронной почте", а почему не использовали System.Net.Mail ?
Решение конечно интересное, но как мне кажется излишне переусложненное.
Дмитрий, Да по сути можно использовать все что работает, от System.IO, до параллельных потоков и Environment, если правильно этим пользоваться.
1) System.IO бесполезен в веб, т.к. на клиенте отображается только результат серверных вычислений, кстати по этой причине Create() любого объекта в клиентском слое будет работать в веб клиенте (но так все равно делать не надо).
2) Как уже писали в статье, в вебе документ не из системы (результат отчета к примеру) можно выгрузить только через IZip, у которого есть метод Export(). Ну или заносить его как SimpleDocument и делать экспорт из него, но это лютый костыль. В десктопе можно массив байт записать сразу на диск или в папку и никаких проблем.
3) В диалогах Desktop клиента можно работать с папками на клиенте, чего не позволяет сделать Web.
4) Рефлексия типа запрещена, но есть моменты когда без нее не обойтись.
Ну и т.д. и т.п.
Если все собрать, то наверное на целую статью хватит.
Сергей, ответа на этот вопрос у меня нет. Нам код достался уже в таком виде, а когда дошло до обновления и решения проблемы, никто из авторов уже не мог вспомнить, почему так написали. Могу лишь предположить, что использовать уже готовый стандартный метод, даже вытащенный таким способом, оказалось быстрее и проще, чем писать собственную логику создания и отправки письма через System.Net.Mail.
Сергей, спасибо за поддержку и развёрнутый ответ :) ключевое здесь - "если правильно этим пользоваться", а с оценкой "правильно или неправильно мы здесь это применяем" на первых порах могут быть проблемы.
Дмитрий, есть ощущение, что одной статьи здесь не хватит но мы подумаем в эту сторону
Авторизуйтесь, чтобы написать комментарий