Разработка и доработка типовых конфигураций на платформе 1С:Предприятие 8.3 иногда преподносят неожиданные сюрпризы при переходе между клиентским и серверным контекстами. Типичная ситуация: в клиентском обработчике формы вызывается серверная процедура, внутри которой создается или модифицируется объект прикладного решения (например, ДокументОбъект). Однако при попытке перехода в серверный метод или в момент вызова метода Записать() платформа аварийно завершает работу с исключением вида: «При подписке ... на событие ПередЗаписью произошла ошибка. Обработчик события не найден».
При этом обработчик подписки физически существует в конфигурации, расположен в общем модуле, у которого установлены флаги Сервер и Внешнее соединение. Разберем детально, почему клиентский вызов провоцирует такую проверку, как на это влияет режим запуска информационной базы и какими способами решается эта неполадка.
Для понимания истоков ошибки проанализируем, как платформа 1С выполняет валидацию метаданных в зависимости от режима работы клиента:
ДокументОбъект и СправочникОбъект полностью недоступны. Любая работа с ними возможна исключительно на сервере. Соответственно, проверка подписок на события объектных данных происходит на стороне сервера, где общий модуль с признаком Сервер полностью доступен, и ошибка не возникает.Клиент (управляемое приложение), платформа считает, что метод обработчика отсутствует в текущей области видимости, и генерирует исключение.Большинство современных типовых решений (таких как «Управление торговлей», «ERP Управление предприятием», «Комплексная автоматизация») спроектированы строго под работу в тонком клиенте или веб-клиенте. Запуск таких систем в режиме толстого клиента управляемого приложения часто приводит к конфликтам доступности контекстов.
Разберем по шагам, как принудительно задать режим тонкого клиента:
/RunModeThickClient и заменим его на ключ /RunModeThinClient.После запуска сеанса в тонком клиенте объектная модель не будет компилироваться на клиенте, и вызов серверной процедуры с созданием документа отработает штатно.
Если ошибка возникает спонтанно в типовом коде или после обновления конфигурации, первоочередной причиной выступает повреждение кэша метаданных. Выполним регламентные действия по очистке и перекомпиляции метаданных:
%LocalAppData%\1C\1cv8\
%AppData%\1C\1cv8\
1C:Enterprise 8.3 Server Agent для сброса серверного кэша.F7). При необходимости выполним сравнение и объединение с эталонным файлом поставки конфигурации для восстановления корректных связей метаданных.Посмотрим на свойства общего модуля, содержащего обработчик подписки. Если подписка привязана к модулю, доступному только на сервере, но контекст ее вызова по какой-то причине требует клиентской доступности, нельзя просто бездумно ставить флаг Клиент (управляемое приложение). Это повлечет за собой необходимость оборачивать весь неклиентский код директивами препроцессора.
Вместо этого проанализируем следующие параметры модуля:
Экспорт:
Процедура ОбработкаПередЗаписьюДокумента(Источник, Отказ, РежимЗаписи, РежимПроведения) Экспорт
// Код логики подписки
КонецПроцедуры
#Если Сервер Тогда
// Обработчик должен быть доступен здесь
#КонецЕсли
Вызов сервера при активном свойстве Сервер. При этом флаг Клиент (управляемое приложение) модулю не требуется.Если проект архитектурно обязан поддерживать запуск толстого клиента управляемого приложения, согласно стандартам разработки 1С код модулей объектов защищают от случайной некорректной компиляции на стороне клиента. Разберем типовой шаблон инструкции препроцессора, который размещают в модуле объекта:
#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
// Основной исполняемый код модуля объекта
#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли
Такая конструкция предотвращает выполнение серверных алгоритмов в неподдерживаемом клиентском окружении и локализует ошибки на этапе компиляции.