Почему на клиенте недоступны свойства объектов в 1С и как это исправить?

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

При переходе на новые релизы платформы или при смене режима работы клиентского приложения разработчики часто сталкиваются с ситуацией, когда привычный код обращения к реквизитам «через точку» на клиенте вызывает ошибку. Например, попытка узнать статус документа с помощью конструкции Объект.АктСписания.Проведен в процедуре с директивой &НаКлиенте перестает работать.

Рассмотрим подробнее, почему возникают подобные ограничения, в чем разница режимов работы клиента и как правильно организовать архитектуру кода в управляемом приложении 1С.

Причина недоступности свойств ссылок на клиенте

Выясним причину такого поведения платформы. На тонком клиенте и веб-клиенте ссылки на объекты базы данных (например, ДокументСсылка, СправочникСсылка) являются «легкими» объектами. Для экономии сетевого трафика и оперативной памяти ссылка на клиенте содержит только базовую информацию:

На тонком клиенте физически отсутствуют реквизиты, табличные части и системные свойства объектов (такие как Проведен или ПометкаУдаления). Попытка размотать цепочку «через точку» от ссылки требует неявного обращения к базе данных, что на тонком клиенте категорически запрещено платформой.

Почему же раньше аналогичный код мог работать?
Чаще всего это происходит при смене режима запуска системы. Если база запускалась в режиме Толстого клиента (управляемое приложение) или в файловом варианте без жесткого разделения контекстов, платформа неявно вычисляла обращения к базе данных на клиенте. Однако при переходе на Тонкий клиент в клиент-серверном режиме работы такое поведение блокируется на архитектурном уровне.

Способ 1. Использование функций БСП (Библиотеки Стандартных Подсистем)

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

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


&НаКлиенте
Процедура ОбработатьДокумент()
    
    // Получаем значение реквизита через серверный вызов
    АктПроведен = ПолучитьСтатусПроведения(Объект.АктСписания);
    
    Если АктПроведен Тогда
        // Выполняем необходимую клиентскую логику
    КонецЕсли;

КонецПроцедуры

&НаСервереБезКонтекста
Функция ПолучитьСтатусПроведения(СсылкаАкт)
    
    Возврат ОбщегоНазначения.ЗначениеРеквизитаОбъекта(СсылкаАкт, "Проведен");

КонецФункции

Если на клиенте требуется проверить сразу несколько реквизитов объекта, воспользуемся функцией ОбщегоНазначения.ЗначенияРеквизитовОбъекта. Она принимает список реквизитов через запятую и возвращает структуру значений:


&НаСервереБезКонтекста
Функция ПолучитьРеквизитыАкта(СсылкаАкт)
    
    // Функция выполнит один точечный запрос к базе данных
    Возврат ОбщегоНазначения.ЗначенияРеквизитовОбъекта(СсылкаАкт, "Проведен, ПометкаУдаления, Дата");

КонецФункции

Способ 2. Использование внеконтекстных серверных вызовов

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

Важно: Обратите внимание на использование директивы &НаСервереБезКонтекста вместо обычного &НаСервере. Внеконтекстный вызов не передает на сервер тяжелый контекст всей формы (структуру Объект), что существенно ускоряет передачу данных по сети.


&НаКлиенте
Процедура ПроверитьСтатусНаКлиенте()

    Если Не ЗначениеЗаполнено(Объект.АктСписания) Тогда
        Возврат;
    КонецЕсли;

    Проведен = ПроверитьАктНаСервере(Объект.АктСписания);
    
    Если Проведен Тогда
        // Выполнение действий
    КонецЕсли;

КонецПроцедуры

&НаСервереБезКонтекста
Функция ПроверитьАктНаСервере(СсылкаНаОбъект)
    
    // На сервере обращение к реквизитам ссылки доступно
    Возврат СсылкаНаОбъект.Проведен;

КонецФункции

Способ 3. Кеширование значений в реквизитах формы

Если параметр ссылочного объекта требуется постоянно использовать в клиентской логике (например, при изменении различных элементов формы или работы с оборудованием), постоянные вызовы сервера будут замедлять интерфейс. В таком случае оптимизируем работу путем создания дополнительного реквизита формы.

  1. Добавим в форму реквизит АктСписанияПроведен с типом Булево.
  2. Заполним его значение на сервере при создании формы или при выборе ссылки.
  3. В клиентских процедурах будем обращаться напрямую к реквизиту формы.

&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    ОбновитьКэшРеквизитов();

КонецПроцедуры

&НаКлиенте
Процедура АктСписанияПриИзменении(Элемент)
    
    // При изменении ссылки обновляем данные на сервере
    ОбновитьКэшРеквизитовНаСервере();

КонецПроцедуры

&НаСервере
Процедура ОбновитьКэшРеквизитовНаСервере()
    
    ОбновитьКэшРеквизитов();

КонецПроцедуры

&НаСервере
Процедура ОбновитьКэшРеквизитов()
    
    Если ЗначениеЗаполнено(Объект.АктСписания) Тогда
        АктСписанияПроведен = Объект.АктСписания.Проведен;
    Иначе
        АктСписанияПроведен = Ложь;
    КонецЕсли;

КонецПроцедуры

Теперь в клиентских обработчиках можно безопасно писать код без обращений к серверу:


&НаКлиенте
Процедура ОбработатьОборудование()
    
    Если АктСписанияПроведен Тогда
        // Логика работы на клиенте
    КонецЕсли;

КонецПроцедуры

Рекомендации по производительности

Посмотрим на основные правила при работе с реквизитами ссылок:

← На главную