При разработке расширений для 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда код, который идеально работает в основной конфигурации, начинает выдавать ошибки внутри расширения. Особенно часто это происходит при попытке выполнить запрос (Запрос.Выполнить()) в контексте HTTP-сервисов или общих модулей. Проблема осложняется тем, что система часто выдает малоинформативные сообщения об ошибках, такие как "Значение не является значением объектного типа (Следующий)".
В этой статье мы подробно проанализируем причины возникновения таких ошибок, разберем правильные подходы к диагностике и выясним, как настройки безопасности влияют на доступ к данным из расширения.
Рассмотрим ситуацию, описанную пользователем: при выполнении запроса в общем модуле расширения возникает ошибка на этапе обхода выборки. Проанализируем исходный фрагмент кода:
Функция ПолучитьМассивСтруктурСкладов() Экспорт
МассивСкладов = Новый Массив;
ЗапросСклады = Новый Запрос;
ЗапросСклады.Текст =
"ВЫБРАТЬ
| Склады.Код КАК Код,
| Склады.Наименование КАК Наименование
|ИЗ
| Справочник.Склады КАК Склады
|ГДЕ
| НЕ Склады.ПометкаУдаления";
Попытка
Выборка = ЗапросСклады.Выполнить().Выбрать();
Исключение
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(ОписаниеОшибки());
КонецПопытки;
Пока Выборка.Следующий() Цикл
МассивСкладов.Добавить(Новый Структура("title, id", СокрЛП(Выборка.Наименование), СокрЛП(Выборка.Код)));
КонецЦикла;
Возврат МассивСкладов;
КонецФункции
В данном коде кроется классическая ошибка логики. Если метод Выполнить() завершается аварией, управление переходит в блок Исключение. После этого выполнение кода продолжается со строки Пока Выборка.Следующий() Цикл. Однако переменная Выборка не была инициализирована (так как произошла ошибка), и попытка вызвать метод Следующий() у неопределенного значения приводит к вторичной ошибке: "Значение не является значением объектного типа (Следующий)". Это маскирует настоящую причину падения самого запроса.
Для корректной диагностики нам необходимо изменить обработку исключений. Рассмотрим правильный вариант:
Попытка
РезультатЗапроса = ЗапросСклады.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Исключение
// Записываем реальную ошибку в журнал регистрации или выводим пользователю
ЗаписьЖурналаРегистрации("ВыполнениеЗапроса", УровеньЖурналаРегистрации.Ошибка,,, ОписаниеОшибки());
Возврат Новый Массив; // Прерываем выполнение функции
КонецПопытки;
Самая распространенная причина, по которой метод Выполнить() в расширении выдает ошибку без подробного описания — это включенный Безопасный режим. Когда расширение работает в безопасном режиме, платформа ограничивает доступ ко многим операциям, включая работу с внешними ресурсами и иногда — специфические манипуляции с данными.
Разберем по шагам, как проверить и изменить этот режим:
Важно: При работе через HTTP-сервис сеанс создается под определенным пользователем. Проверьте, имеет ли этот пользователь права на чтение объектов, к которым обращается запрос в расширении.
Иногда запрос обращается к данным, доступ к которым ограничен на уровне RLS (Record Level Security). В контексте расширений RLS может вести себя иначе, чем в основной конфигурации. Чтобы исключить влияние прав доступа, проанализируем возможность использования привилегированного режима.
В модуле расширения мы можем явно вызвать команду УстановитьПривилегированныйРежим(Истина). Но помните: если расширение работает в безопасном режиме, эта команда будет проигнорирована платформой. Только отключение безопасного режима позволит коду расширения выполняться с полными правами.
Посмотрим на ситуацию с добавлением объектов в расширение. В платформе 8.3 существует правило: для того чтобы конструктор запросов "видел" объект, его нужно добавить в расширение. Однако для простого выполнения программного запроса это не всегда обязательно.
Тем не менее, существуют нюансы:
Код или Наименование), которые в основной конфигурации управляются Функциональными опциями, запрос может вернуть ошибку, если эти опции не "захвачены" в расширение вместе с объектом.Если запрос продолжает выдавать ошибку "Ошибка при вызове метода контекста (Выполнить)", выполним следующую последовательность действий:
Выборка = Запрос.Выполнить().Выбрать(); напишем три разные строки. Это позволит в отладчике точно увидеть, где происходит сбой — в момент создания Новый Запрос, в момент Выполнить() или Выбрать().snccntx на сервере.default.vrd. В нем не должно быть запретов на использование расширений (параметр allowExtensions должен быть истинным).Таким образом, успех выполнения запроса в расширении зависит не только от правильности текста запроса, но и от сложной комбинации настроек безопасности, контекста выполнения и прав доступа сеанса.