Разработка веб-сервисов в среде 1С:Предприятие 8.3 — задача ответственная, требующая понимания не только встроенного языка, но и механизмов сериализации данных, работы сеансов и прав доступа. Часто программисты сталкиваются с необъяснимым на первый взгляд поведением: при обращении к реквизитам объекта через точку от ссылки в модуле веб-сервиса возвращается NULL. Это происходит даже тогда, когда объект гарантированно существует в базе данных.
В этой статье мы подробно разберем, почему возникает такая ситуация, проанализируем типичные ошибки разработчиков и изучим глубокие системные механизмы платформы, которые могут приводить к подобному результату.
Рассмотрим самую простую, но крайне распространенную причину. Если в справочнике используется иерархия «Групп и элементов», то платформа физически разделяет поля в таблицах базы данных. Многие реквизиты, созданные программистом, по умолчанию имеют настройку «Использовать для элементов», но не для групп.
Проанализируем ситуацию: вы ищете объект по коду, но ошибочно указываете код группы. В этом случае Справочники.Номенклатура.НайтиПоКоду("001") вернет валидную ссылку на группу. Однако при обращении к реквизиту, который предназначен только для элементов, платформа вернет NULL, так как в строке таблицы БД, соответствующей группе, это поле просто не существует или не заполнено.
Чтобы избежать этой ловушки, в коде веб-сервиса всегда следует выполнять проверку типа объекта:
СсылкаНаОбъект = Справочники.Номенклатура.НайтиПоКоду(КодИзЗапроса);
Если СсылкаНаОбъект.Пустая() Тогда
// Обработка ситуации, когда объект не найден
ИначеЕсли СсылкаНаОбъект.ЭтоГруппа Тогда
// Логика для группы, где многие реквизиты будут NULL
ЗаписьЖурналаРегистрации("ОшибкаВебСервиса", УровеньЖурналаРегистрации.Предупреждение, , , "Передан код группы вместо элемента.");
Иначе
Значение = СсылкаНаОбъект.НаименованиеПолное;
КонецЕсли;
Одной из наиболее неочевидных причин появления NULL является работа механизма Row Level Security (RLS). Веб-сервисы часто работают под специально созданными пользователями с ограниченными правами.
Выясним причину: если у пользователя есть право на чтение самого объекта (ссылки), но ограничены права на чтение конкретных полей (реквизитов), платформа 1С при обращении к этим полям через точку или в запросе вернет именно NULL. Это сделано для того, чтобы не вызывать исключение «Нарушение прав доступа» при выполнении массовых операций или сериализации объектов XDTO, позволяя коду продолжать работу.
Для диагностики этой проблемы выполните следующие шаги:
ВЫБРАТЬ РАЗРЕШЕННЫЕ. Если поле возвращает NULL, значит, права на чтение данного реквизита отсутствуют.Веб-сервисы 1С не передают данные напрямую, они используют пакеты XDTO (XML Data Transfer Objects). При формировании ответа платформа выполняет преобразование типов 1С в типы XML. Здесь кроется важный нюанс: если в определении типа свойства в XDTO-пакете стоит флаг Nillable (допускает пустое значение), то любые «пустые» значения 1С могут трансформироваться.
Рассмотрим подробнее: в 1С пустая ссылка — это не NULL, а специфическое значение. Однако при передаче через веб-сервис платформа может решить, что пустую ссылку проще представить как xsi:nil="true". При обратной десериализации (например, в мобильном приложении или другом сервисе) это значение превращается в NULL. В версиях платформы 8.3.13 этот механизм иногда срабатывал некорректно даже внутри серверного контекста при обработке объектов, пришедших извне.
Чтобы минимизировать риски, используйте метод ЗначениеЗаполнено() вместо прямого сравнения с NULL или Неопределено.
Если реквизит, к которому вы обращаетесь, управляется Функциональной опцией (ФО), и эта опция в текущем сеансе веб-сервиса выключена, вы получите NULL.
Проанализируем ситуацию: сеанс веб-сервиса инициализируется с параметрами по умолчанию. Если логика включения функциональной опции завязана на параметры сеанса (например, «Текущий склад» или «Организация»), которые не были установлены при старте веб-сервиса, то реквизиты, зависящие от этой ФО, станут «невидимыми» для платформы, и обращение к ним вернет пустое значение (NULL).
Рекомендуется в начале работы метода веб-сервиса принудительно устанавливать необходимые параметры сеанса:
ПараметрыСеанса.ТекущийПользователь = АвторизованныйПользователь;
// Установка других параметров, влияющих на ФО
Иногда в веб-сервис передается GUID (уникальный идентификатор), который отсутствует в текущей базе данных. 1С создает так называемую «битую ссылку» (Объект не найден). В обычном клиентском приложении обращение к реквизиту такой ссылки вызвало бы ошибку или вернуло Неопределено.
Однако в контексте веб-сервиса при формировании XML-ответа платформа старается избегать аварийного завершения потока. Если объект не найден в БД, обращение к его полям через точку в запросах или при выгрузке в XDTO часто возвращает NULL.
Также стоит учитывать баг кэширования, характерный для платформы 8.3.13. Если веб-сервис работает в режиме повторного использования сеансов, кэш объектов может не обновляться своевременно. Если объект был удален в другом сеансе, веб-сервис может хранить ссылку в памяти, но при попытке чтения данных из БД получать NULL.
Если ваш веб-сервис работает с данными из Внешних источников данных (например, таблицы SQL, подключенные через ODBC), поведение системы меняется. В «родных» таблицах 1С почти все поля имеют значения по умолчанию (пустая строка, число 0). Во внешних же базах данных поля часто имеют значение DBNULL.
При чтении данных из внешней таблицы через веб-сервис 1С честно транслирует DBNULL как NULL. Это единственный легальный случай, когда реквизит реально существующей записи будет иметь тип NULL без каких-либо ошибок настройки прав или иерархии.
Если вы столкнулись с NULL в веб-сервисе, пройдите по шагам:
ЭтоГруппа.NULL исчез — настраивайте RLS.ПолучитьОбъект() не возвращает Неопределено.Nillable и MinOccurs).Использование этих методов позволит вам быстро локализовать причину и обеспечить стабильную работу интеграционных решений на базе платформы 1С.