Работа с веб-сервисами в системе 1С:Предприятие требует особого внимания к контексту исполнения кода. Часто разработчики сталкиваются с ситуацией, когда при вызове метода СоздатьДокумент() через внешнее соединение или веб-сервис сеанс просто «вылетает» без каких-либо явных ошибок в Журнале регистрации. В этой статье мы подробно разберем, почему это происходит, как диагностировать проблему и как правильно писать код модулей объектов, чтобы они корректно работали в разных режимах.
Рассмотрим типичную ситуацию: веб-сервис успешно создает документ РеализацияТоваровУслуг, но при попытке создать ПеремещениеТоваров соединение обрывается. Отладка показывает, что выполнение останавливается ровно на строке Документы.ПеремещениеТоваров.СоздатьДокумент(). При этом система не заходит внутрь модуля объекта, не выдает исключение в блоке Попытка...Исключение и не записывает ошибку в ЖР.
Выясним причину: в момент вызова СоздатьДокумент() сервер 1С выполняет компиляцию всего модуля объекта. Если в модуле содержится синтаксическая ошибка или обращение к методу, недоступному на сервере (например, Вопрос() или Предупреждение()), и этот вызов не обернут в инструкции препроцессора, сервер не может скомпилировать контекст объекта. В режиме веб-сервиса это часто приводит к аварийному завершению рабочего процесса rphost или обрыву соединения IIS, что внешне выглядит как «тихое» падение.
Если обычный отладчик не позволяет зайти внутрь метода СоздатьДокумент(), проанализируем ситуацию с помощью замера производительности. Это поможет понять, выполнялся ли какой-то код внутри модуля или система «упала» на этапе инициализации.
Если в замере мы видим, что 99% времени потрачено на строку создания объекта и нет ни одного захода в процедуры модуля (такие как ПередЗаписью или ПриУстановкеНовогоНомера), значит, проблема именно в компиляции модуля.
Разберем основной источник бед в типовых и старых самописных конфигурациях (например, УПП). В модулях объектов часто встречаются вызовы клиентских методов, которые должны срабатывать только при работе пользователя в интерфейсе. Рассмотрим пример опасного кода в модуле объекта:
Процедура ПроверитьЗаполнениеДанных()
Если Не ЗначениеЗаполнено(Склад) Тогда
ТекстВопроса = "Склад не заполнен. Продолжить?";
Ответ = Вопрос(ТекстВопроса, РежимДиалогаВопрос.ДаНет); // ОШИБКА: метод недоступен на сервере
Если Ответ = КодВозвратаДиалога.Нет Тогда
Отказ = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
При работе через веб-сервис сервер 1С пытается скомпилировать этот код. Поскольку функция Вопрос() не существует в контексте сервера, компилятор выдает критическую ошибку. Чтобы этого избежать, мы должны использовать инструкции препроцессора.
Рассмотрим, как правильно изолировать клиентский код. Важно понимать, что обернуть нужно не только сам вызов метода, но и всю логику, которая не имеет смысла на сервере. Проанализируем правильный вариант:
#Если Клиент Тогда
// Этот код будет скомпилирован только на стороне клиента
ТекстВопроса = "Вы уверены, что хотите провести документ?";
Если Вопрос(ТекстВопроса, РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Нет Тогда
Возврат;
КонецЕсли;
#КонецЕсли
Важный нюанс: если вы вызываете свою функцию из модуля объекта, которая содержит интерактивные элементы, она также должна быть защищена. Например, если у вас есть функция СообщитьПользователюОбОшибке(), проверьте ее содержимое. Даже если вы не планируете вызывать эту функцию через веб-сервис, само ее наличие в модуле без препроцессора «сломает» создание объекта.
Чтобы не искать такие ошибки вручную по всем модулям, воспользуемся встроенным инструментом 1С. Рассмотрим алгоритм проверки:
Система выдаст список всех мест, где используются недопустимые методы в серверном контексте. Проанализируем этот список и добавим #Если Клиент Тогда там, где это необходимо.
Часто в обсуждениях советуют устанавливать свойство ОбменДанными.Загрузка = Истина. Посмотрим, почему в данной ситуации это бесполезно. Это свойство влияет на логику работы уже созданного объекта (позволяет обходить проверки в обработчиках ПередЗаписью и т.д.). Однако в нашем случае падение происходит на этапе инстанцирования (создания) объекта в памяти сервера. До того как мы сможем присвоить значение этому свойству, сервер должен успешно скомпилировать модуль объекта, что у него не получается из-за синтаксической ошибки (недоступного метода).
Для предотвращения подобных проблем в будущем, рекомендуем придерживаться следующих правил при проектировании системы:
Вопрос, Предупреждение, ВвестиЗначение) непосредственно из модуля объекта. Эти вызовы должны находиться в модуле формы.rphost.exe с кодом 0xc0000005 подтвердят, что проблема носит характер критического сбоя памяти при попытке выполнить недопустимую инструкцию.Таким образом, мы выяснили, что причиной падения сеанса при работе через веб-сервис чаще всего является «забытый» интерактивный код в модуле объекта. Своевременная проверка синтаксиса в режиме «Сервер» и «Внешнее соединение» позволяет предотвратить такие ситуации еще на этапе разработки.