Почему возникает ошибка «Метод объекта не обнаружен (УникальныйИдентификатор)» и как её исправить?

Программист 1С v8.3 (Обычные формы) IT и автоматизация бизнеса
← На главную

Нередко разработчики сталкиваются с ситуацией, когда программный код в конфигурации 1С идеально работает под учетной записью с полными правами, но падает с критической ошибкой Метод объекта не обнаружен (УникальныйИдентификатор) у пользователей с ограниченными правами. Первой реакцией часто становится поиск недостающей роли, права на чтение или просмотр объекта. Однако в большинстве случаев права доступа не имеют к этой проблеме прямого отношения. Разберем детально, почему возникает такое исключение, как локализовать проблему и как правильно доработать программный код.

В чем кроется истинная причина ошибки

Метод УникальныйИдентификатор() доступен исключительно для ссылочных типов данных платформы 1С: СправочникСсылка, ДокументСсылка, ПланВидовХарактеристикСсылка и других аналогичных типов. Если переменная содержит любой другой тип данных, платформа закономерно сообщает, что указанный метод у объекта отсутствует.

Иллюзия того, что ошибка зависит от назначенных ролей или RLS (ограничения доступа на уровне записей), обычно возникает при работе с отчетами и динамическими списками. Рассмотрим основные сценарии, которые к этому приводят:

  1. Разные сохраненные настройки отчетов: Пользователи сохраняют персональные варианты настроек и отборов. Если администратор использовал вид сравнения «Равно», значением отбора являлась одиночная ссылка (например, СправочникСсылка.Номенклатура). Пользователь с ограниченными правами настроил отбор через вид сравнения «В списке» или «В группе из списка», из-за чего платформа автоматически преобразовала тип значения отбора в СписокЗначений. Попытка выполнить Отбор.Номенклатура.Значение.УникальныйИдентификатор() для списка значений неизбежно вызовет ошибку.
  2. Обращение к объекту вместо ссылки: У объектов модификации данных (например, СправочникОбъект.Номенклатура) метода УникальныйИдентификатор() нет. Идентификатор хранится только в ссылочной структуре.
  3. Пустые или неинициализированные значения: Если пользователь не заполнил поле отбора или реквизит, в переменную попадает значение Неопределено, NULL или пустая строка, не обладающие искомым методом.
  4. Поведение RLS: Ограничения на уровне записей никогда не вызывают ошибку отсутствия метода ссылки. Даже если у пользователя нет прав на просмотр конкретного элемента справочника, сама ссылка в оперативной памяти содержит UUID. Ошибка прав возникает только при попытке разыменования реквизитов через точку (например, при обращении к наименованию объекта), тогда как вызов Ссылка.УникальныйИдентификатор() успешно отрабатывает даже для недоступных по RLS данных.

Способ 1. Проверка типа значения перед вызовом метода

Проанализируем базовый защитный механизм. Прежде чем обращаться к специфическим методам ссылки, необходимо убедиться, что тип переменной действительно соответствует ожиданиям. Для этого можно использовать проверку на конкретный ссылочный тип или универсальные механизмы Библиотеки стандартных подсистем (БСП).

Рассмотрим вариант явной проверки типа значения:


Если ТипЗнч(Значение) = Тип("СправочникСсылка.Номенклатура") Тогда
    Идентификатор = Значение.УникальныйИдентификатор();
Иначе
    // Обработка ситуации, когда передана не ссылка
    Идентификатор = Неопределено;
КонецЕсли;

Если в конфигурации внедрена БСП, удобнее использовать универсальную функцию, проверяющую ссылочную природу переданного значения:


Если ОбщегоНазначенияКлиентСервер.ЭтоСсылка(Значение) Тогда
    Идентификатор = Значение.УникальныйИдентификатор();
КонецЕсли;

Способ 2. Корректная обработка СпискаЗначений

Разберем ситуацию, когда реквизит или параметр отбора содержит коллекцию элементов. Если пользователь настроил множественный отбор, переданная переменная будет иметь тип СписокЗначений. В этом случае мы должны обойти коллекцию в цикле и извлечь идентификаторы из свойства Значение каждого элемента списка.

Посмотрим на пример комплексной обработки, поддерживающей как одиночные ссылки, так и списки:


МассивИдентификаторов = Новый Массив;

Если ТипЗнч(ЗначениеОтбора) = Тип("СписокЗначений") Тогда
    Для Каждого ЭлементСписка Из ЗначениеОтбора Цикл
        Если ОбщегоНазначенияКлиентСервер.ЭтоСсылка(ЭлементСписка.Значение) Тогда
            МассивИдентификаторов.Добавить(ЭлементСписка.Значение.УникальныйИдентификатор());
        КонецЕсли;
    КонецЦикла;
ИначеЕсли ОбщегоНазначенияКлиентСервер.ЭтоСсылка(ЗначениеОтбора) Тогда
    МассивИдентификаторов.Добавить(ЗначениеОтбора.УникальныйИдентификатор());
КонецЕсли;

Способ 3. Получение идентификатора у объектов и новых элементов

Если в коде происходит работа не с отборами, а с прикладными объектами в процессе их редактирования, обращаться к идентификатору необходимо строго через свойство Ссылка. Проанализируем различия в получении идентификатора для существующих и новых объектов:

  1. Для существующего объекта: Идентификатор = ОбъектСправочника.Ссылка.УникальныйИдентификатор();
  2. Для нового объекта (еще не записанного в базу): У созданного через СоздатьЭлемент() объекта свойство Ссылка возвращает пустую ссылку. Чтобы получить или принудительно задать идентификатор до момента фактической записи в базу данных, воспользуемся методами ПолучитьСсылкуНового() и УстановитьСсылкуНового():
    
    НоваяСсылка = ОбъектСправочника.ПолучитьСсылкуНового();
    Если Не ЗначениеЗаполнено(НоваяСсылка) Тогда
        НоваяСсылка = Справочники.Номенклатура.ПолучитьСсылку();
        ОбъектСправочника.УстановитьСсылкуНового(НоваяСсылка);
    КонецЕсли;
    Идентификатор = НоваяСсылка.УникальныйИдентификатор();
    

Альтернативный вариант: функция XMLСтрока

Если конечной целью является получение строкового представления уникального идентификатора (например, для передачи данных во внешнюю систему или веб-сервис), рассмотрим использование системной функции платформы XMLСтрока().

Посмотрим на пример вызова функции:


Если ОбщегоНазначенияКлиентСервер.ЭтоСсылка(ТекущаяНоменклатура) Тогда
    СтрокаГУИД = XMLСтрока(ТекущаяНоменклатура);
КонецЕсли;

Важный нюанс: функция XMLСтрока() работает быстрее, чем связка Строка(Ссылка.УникальныйИдентификатор()), однако она точно так же требует передачи ссылки. Если передать в нее СписокЗначений, платформа сгенерирует другую ошибку сериализации, поэтому предварительная проверка типа значения остается обязательной.

Алгоритм диагностики ошибки

Чтобы быстро найти корень проблемы в рабочей базе, выполним следующие шаги:

  1. Подключимся отладчиком к сеансу пользователя с ограниченными правами.
  2. Поставим точку останова на проблемной строке перед вызовом метода УникальныйИдентификатор().
  3. В окне вычисления выражений проверим тип проблемной переменной с помощью конструкции ТипЗнч(ИмяПеременной).
  4. Убедившись, что в переменной находится СписокЗначений, массив или значение Неопределено, скорректируем программный код добавлением условий на проверку типов.
← На главную