При разработке веб-сервисов в среде 1С:Предприятие программисты часто сталкиваются с ситуацией, когда вызов, казалось бы, простой процедуры из общего модуля приводит к немедленному прекращению сеанса отладки или неочевидным ошибкам. Рассмотрим ситуацию, когда из метода веб-сервиса вызывается процедура отправки почты, расположенная в общем модуле, и разберем, почему стандартные действия (вроде изменения флажков в свойствах модуля) не всегда помогают.
Проанализируем поведение системы в момент обращения к веб-сервису. Веб-сервис всегда исполняется на стороне сервера в неинтерактивном режиме. Когда код доходит до точки вызова ОбщийМодульКлиент.ОтправитьСообщение, сервер 1С должен скомпилировать этот модуль для текущего контекста исполнения. Если в модуле присутствуют ошибки компиляции, выполнение прерывается мгновенно.
Основная ошибка заключается в том, что разработчики пытаются вызвать код, который физически не может существовать на сервере. Рассмотрим подробнее, что происходит при попытке просто «поставить галочки» Сервер, Клиент и Внешнее соединение в свойствах общего модуля. Если внутри модуля содержатся методы, доступные только в интерфейсе (например, Предупреждение(), Вопрос(), ПоказатьОповещениеПользователя()), то при попытке сервера скомпилировать этот модуль возникнет критическая ошибка. Сервер «не знает», что такое диалоговое окно, и компиляция всего модуля целиком завершается неудачей еще до того, как начнет выполняться ваша конкретная процедура.
Выясним важный нюанс: нельзя просто так смешивать клиентский и серверный контекст. Посмотрим на основные правила:
Проанализируем пример использования директив препроцессора, которые позволяют «спрятать» клиентский код от сервера:
#Если Клиент Тогда
Процедура ПоказатьДиалог()
Предупреждение("Сообщение для пользователя");
КонецПроцедуры
#КонецЕсли
В этом случае сервер при компиляции просто проигнорирует блок между #Если Клиент и #КонецЕсли, и модуль будет успешно загружен в серверную память.
Рассмотрим по шагам, как правильно реализовать задачу отправки сообщения из веб-сервиса, чтобы избежать ошибок. Наилучшим архитектурным решением будет разделение логики на клиентскую и серверную части.
Вместо того чтобы пытаться адаптировать клиентский модуль, создадим новый общий модуль, например, РаботаСПочтойСервер. В его свойствах установим только галочку Сервер. Если процедура должна выполнять действия, требующие повышенных прав (например, запись в журнал регистрации или чтение защищенных данных), установим флаг Привилегированный.
Посмотрим на пример кода, который будет стабильно работать в контексте веб-сервиса. Помните, что на сервере нельзя использовать почтовые клиенты (COM-объекты Outlook и подобные). Нужно использовать исключительно объект ИнтернетПочта.
// В модуле РаботаСПочтойСервер
Процедура ОтправитьПисьмоНаСервере(ПараметрыСообщения, Состояние) Экспорт
// Подготавливаем структуру сообщения
Письмо = Новый ИнтернетПочтовоеСообщение;
Письмо.Тема = "Уведомление по заявке: " + ПараметрыСообщения.Обращение;
Письмо.Тексты.Добавить(ПараметрыСообщения.ПричинаВозвратаВработу);
// Здесь должна быть логика настройки профиля и отправки через ИнтернетПочта
// ...
ЗаписьЖурналаРегистрации("ОтправкаПочты", УровеньЖурналаРегистрации.Информационный, , , "Письмо отправлено для ID: " + ПараметрыСообщения.УникальныйИдентификатор);
КонецПроцедуры
Теперь в теле метода вашего веб-сервиса обращение будет выглядеть следующим образом:
Процедура ВыполнитьЗапросВебСервиса(Данные)
ПараметрыСообщения = Новый Структура;
ПараметрыСообщения.Вставить("УникальныйИдентификатор", Данные.id);
ПараметрыСообщения.Вставить("Обращение", Данные.Заявка);
ПараметрыСообщения.Вставить("ПричинаВозвратаВработу", Данные.Комментарий);
Попытка
// Вызываем именно серверный модуль
РаботаСПочтойСервер.ОтправитьПисьмоНаСервере(ПараметрыСообщения, Данные.Состояние);
Исключение
// Обязательно фиксируем ошибку в Журнале Регистрации,
// так как в веб-сервисе пользователь не увидит сообщение об ошибке
ЗаписьЖурналаРегистрации("ОшибкаВебСервиса",
УровеньЖурналаРегистрации.Ошибка, , ,
ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Если отладка все же «вылетает», проанализируем настройки вашего сервера. Отладка веб-сервисов имеет свои особенности:
/debug. Без этого ключа точка останова в серверном коде никогда не сработает.default.vrd разрешена отладка (параметр debug="true").Подводя итог, можно сказать, что решение проблемы кроется в строгом соблюдении контекстности. Никогда не вызывайте клиентские модули из веб-сервисов. Выносите всю общую логику в серверные модули, очищая их от любых интерактивных функций. Это обеспечит стабильную работу ваших интеграционных решений и предсказуемое поведение системы при отладке.