Как исправить ошибку «Отсутствует отображение для типа» при работе с фоновыми и регламентными заданиями в 1С?

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

При разработке управляемых форм в платформе «1С:Предприятие 8.3» разработчики регулярно сталкиваются с контекстной изоляцией клиентского и серверного кода. Одной из наиболее распространенных ошибок при попытке отобразить список заданий или настроить по ним фильтрацию является сообщение: «Отсутствует отображение для типа "СостояниеФоновогоЗадания"» или «Отсутствует отображение для типа "РегламентноеЗадание"».

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

Архитектурная причина ошибки

Проанализируем, как работает клиент-серверное взаимодействие в управляемом приложении. При выполнении серверного вызова из формы платформа собирает контекст формы на клиенте, сериализует его, отправляет на сервер, выполняет процедуру, а затем сериализует результат и возвращает его обратно в браузер или тонкий клиент.

Далеко не все типы данных платформы 1С могут существовать в контексте Тонкого клиента или Веб-клиента. Согласно синтакс-помощнику, такие типы, как СостояниеФоновогоЗадания, ФоновоеЗадание, РегламентноеЗадание, имеют контекст доступности: Сервер, толстый клиент, внешнее соединение.

Когда мы пытаемся поместить значение недоступного типа в реквизит формы, в колонку таблицы формы или в возвращаемую структуру, платформа пытается выполнить сериализацию типа, для которого у тонкого клиента нет соответствующего аналога (отображения). В этот момент и возникает исключение «Отсутствует отображение для типа...».

Типичные места возникновения ошибки в коде

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

  1. Передача массива перечислений из диалога отбора на клиент. Попытка сформировать массив из элементов СостояниеФоновогоЗадания.Завершено и передать его через параметр формы или структуру закрытия диалога.
  2. Сохранение перечисления в реквизите формы. Если в управляемой форме создан реквизит с произвольным типом или типом Структура (например, ОтборФоновыхЗаданий), и внутри него лежит массив системных перечислений, ошибка упадет в момент завершения любого серверного вызова.
  3. Заполнение колонок таблицы формы серверными объектами. Присвоение значения в цикле вида НоваяСтрока.Состояние = Фоновое.Состояние; в случае, если колонка формы не имеет строкового типа.
  4. Добавление серверных объектов в список выбора. Попытка добавить ссылку на объект РегламентноеЗадание прямо в свойство СписокВыбора элемента формы.

Решение 1. Правильная работа с отбором по состояниям фоновых заданий

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

Посмотрим на пример кода формы фильтра (диалога настройки отбора), где отбор формируется в виде массива строковых имен:


&НаСервере
Процедура ЗаполнитьОтборНаСервере(СтруктураОтбора)
    
    МассивСостояний = Новый Массив;
    
    // Вместо прямой передачи элементов перечисления передаем их строковые идентификаторы
    Если ОтборВыполняется Тогда
        МассивСостояний.Добавить("Активно");
    КонецЕсли;
    
    Если ОтборВыполнено Тогда
        МассивСостояний.Добавить("Завершено");
    КонецЕсли;
    
    Если ОтборВыполненоСОшибкой Тогда
        МассивСостояний.Добавить("ЗавершеноАварийно");
    КонецЕсли;
    
    Если ОтборОтменено Тогда
        МассивСостояний.Добавить("Отменено");
    КонецЕсли;
    
    Если МассивСостояний.Количество() > 0 Тогда
        СтруктураОтбора.Вставить("Состояние", МассивСостояний);
    КонецЕсли;
    
КонецПроцедуры

Теперь разберем, как принять эту структуру на сервере основной формы и выполнить поиск заданий через менеджер ФоновыеЗадания. Для преобразования строки в системное перечисление воспользуемся обращением по индексу через квадратные скобки: СостояниеФоновогоЗадания[ИмяСостояния].


&НаСервере
Процедура ПрименитьОтборИОбновитьТаблицуНаСервере(СтруктураОтбораКлиент)
    
    ОтборДляПоиска = Новый Структура;
    
    // Копируем базовые поля
    Если СтруктураОтбораКлиент.Свойство("Ключ") Тогда
        ОтборДляПоиска.Вставить("Ключ", СтруктураОтбораКлиент.Ключ);
    КонецЕсли;
    
    // Преобразуем строковые состояния в системные перечисления
    Если СтруктураОтбораКлиент.Свойство("Состояние") И ТипЗнч(СтруктураОтбораКлиент.Состояние) = Тип("Массив") Тогда
        МассивПеречислений = Новый Массив;
        Для Каждого ИмяСостояния Из СтруктураОтбораКлиент.Состояние Цикл
            // Преобразование строки в значение перечисления
            МассивПеречислений.Добавить(СостояниеФоновогоЗадания[ИмяСостояния]);
        КонецЦикла;
        
        Если МассивПеречислений.Количество() > 0 Тогда
            ОтборДляПоиска.Вставить("Состояние", МассивПеречислений);
        КонецЕсли;
    КонецЕсли;
    
    // Получаем массив фоновых заданий
    НайденныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(ОтборДляПоиска);
    
    // Заполняем таблицу формы
    ТаблицаФоновыеЗадания.Очистить();
    Для Каждого Фоновое Из НайденныеЗадания Цикл
        НоваяСтрока = ТаблицаФоновыеЗадания.Добавить();
        НоваяСтрока.Идентификатор = Фоновое.УникальныйИдентификатор;
        НоваяСтрока.Наименование  = Фоновое.Наименование;
        НоваяСтрока.Ключ          = Фоновое.Ключ;
        НоваяСтрока.ИмяМетода     = Фоновое.ИмяМетода;
        НоваяСтрока.Начало        = Фоновое.Начало;
        НоваяСтрока.Конец         = Фоновое.Конец;
        
        // ВНИМАНИЕ: Приводим состояние к строке для отображения на клиенте!
        НоваяСтрока.Состояние     = Строка(Фоновое.Состояние);
        
        Если Фоновое.ИнформацияОбОшибке <> Неопределено Тогда
            НоваяСтрока.Ошибки = Фоновое.ИнформацияОбОшибке.Описание;
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Решение 2. Исправление ошибки с типом «РегламентноеЗадание»

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


// ОШИБОЧНЫЙ КОД:
Элементы.ОтборРегламентноеЗадание.СписокВыбора.Добавить(РегламентноеЗадание, РегламентноеЗадание);

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

Для безопасной передачи используем уникальный идентификатор задания (тип УникальныйИдентификатор или Строка) в качестве значения, а понятное строковое наименование — в качестве представления:


&НаСервере
Процедура ЗаполнитьСписокВыбораРегламентныхЗаданий()
    
    СписокВыбораЭлемента = Элементы.ОтборРегламентноеЗадание.СписокВыбора;
    СписокВыбораЭлемента.Очистить();
    
    // Получаем массив всех регламентных заданий базы данных
    МассивРегламентных = РегламентныеЗадания.ПолучитьРегламентныеЗадания();
    
    Для Каждого Задание Из МассивРегламентных Цикл
        
        // Формируем понятное пользователю представление
        ПредставлениеЗадания = Задание.Наименование;
        Если ПустаяСтрока(ПредставлениеЗадания) Тогда
            ПредставлениеЗадания = Задание.Метаданные.Синоним;
        КонецЕсли;
        
        // Добавляем в список выбора пару: УникальныйИдентификатор (или строка) и Текст
        СписокВыбораЭлемента.Добавить(
            Строка(Задание.УникальныйИдентификатор), 
            ПредставлениеЗадания
        );
        
    КонецЦикла;
    
КонецПроцедуры

Когда пользователь выберет нужное регламентное задание в поле ввода на клиенте, в реквизит формы запишется строковый идентификатор. Затем на сервере мы легко найдем исходный объект по его идентификатору:


&НаСервере
Функция ПолучитьОбъектРегламентногоЗаданияПоИдентификатору(ИдентификаторСтрокой)
    
    Если ПустаяСтрока(ИдентификаторСтрокой) Тогда
        Возврат Неопределено;
    КонецЕсли;
    
    ГУИД = Новый УникальныйИдентификатор(ИдентификаторСтрокой);
    Возврат РегламентныеЗадания.НайтиПоУникальномуИдентификатору(ГУИД);
    
КонецФункции

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

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

  1. Проверяйте доступность типа по синтакс-помощнику. Если у типа не указан контекст «Тонкий клиент» или «Веб-клиент», его экземпляры ни при каких обстоятельствах не должны попадать в реквизиты формы, параметры процедур с директивой &НаКлиенте или таблицы формы.
  2. Используйте строковую сериализацию. Для системных перечислений используйте преобразование через Строка(Значение) (для вывода пользователю) или XMLСтрока(Значение) (для программной обработки), а на сервере восстанавливайте через конструкцию ПеречислениеТип[ИмяСтрокой].
  3. Храните ссылки на объекты через идентификаторы. Для серверных объектов (фоновые задания, регламентные задания, сеансы) на форме храните только их УникальныйИдентификатор.

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

← На главную