При разработке в среде 1С:Предприятие 8.3 на управляемых формах начинающие специалисты часто сталкиваются с ошибкой: «Ошибка передачи данных между клиентом и сервером. Значение недопустимого типа. Ошибка отображения типов: Отсутствует отображение для типа "ФормаКлиентскогоПриложения"». Эта проблема является фундаментальной и связана с непониманием архитектуры клиент-серверного взаимодействия. В данной статье мы подробно разберем, почему возникает эта ошибка, как оптимизировать поиск данных и как правильно открывать формы существующих документов.
Разберем ситуацию: в коде управляемого приложения существует жесткое разделение на клиентский контекст (где работает интерфейс и пользователь) и серверный контекст (где происходит работа с базой данных). Передача данных между ними осуществляется посредством механизма сериализации XDTO. Это означает, что любой объект, который вы хотите передать с сервера на клиент (или наоборот), должен быть «упакован» в понятный платформе формат.
Тип ФормаКлиентскогоПриложения (или ManagedForm) является сложным объектом интерфейса. Платформа 1С не умеет сериализовать «живой» объект формы для передачи по каналу связи. Когда вы вызываете на сервере метод ПолучитьФорму(), объект формы создается в памяти сервера. Попытка вернуть этот объект в клиентскую процедуру через оператор Возврат вызывает критический сбой, так как клиент не знает, что делать с «серверным призраком» формы.
Запомним главное правило: формы нельзя передавать между клиентом и сервером. Формы нужно открывать непосредственно на клиенте, используя ссылки на объекты.
Рассмотрим пример кода, который привел к ошибке в сообщении пользователя:
&НаСервере
Функция ОплатаДопУслуг(ФЛ)
Выб = Документы.ДопУслуга.Выбрать();
Пока Выб.Следующий() Цикл
Если Строка(Выб.ФизЛицо) = Строка(ФЛ) Тогда
Об = Выб.Ссылка.ПолучитьФорму("ФормаДокумента", Выб);
КонецЕсли;
КонецЦикла;
Возврат Об; // Здесь происходит ошибка!
КонецФункции
В этом фрагменте мы видим сразу три серьезные методологические ошибки:
Об) с сервера на клиент.Выбрать() для поиска конкретного документа. Если в базе будет 100 000 документов, система начнет перебирать их все, что приведет к колоссальным задержкам.Строка(). Сравнение строковых представлений ссылок — это крайне медленная операция, которая к тому же может давать ложные результаты при совпадении наименований.Для решения задачи нам необходимо разделить логику на два этапа: эффективный поиск ссылки на документ на сервере и открытие формы по этой ссылке на клиенте.
Вместо перебора всех документов Документы.ДопУслуга.Выбрать(), мы воспользуемся механизмом запросов. Запросы работают напрямую с СУБД и используют индексы, что делает поиск практически мгновенным.
Проанализируем пример серверной функции:
&НаСервереБезКонтекста
Функция НайтиДокументДопУслуги(ФизЛицоСсылка)
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 1
| ДопУслуга.Ссылка КАК Ссылка
|ИЗ
| Документ.ДопУслуга КАК ДопУслуга
|ГДЕ
| ДопУслуга.ФизЛицо = &ФизЛицо
| И НЕ ДопУслуга.ПометкаУдаления";
Запрос.УстановитьПараметр("ФизЛицо", ФизЛицоСсылка);
РезультатЗапроса = Запрос.Выполнить();
Если НЕ РезультатЗапроса.Пустой() Тогда
Выборка = РезультатЗапроса.Выбрать();
Выборка.Следующий();
Возврат Выборка.Ссылка; // Возвращаем ССЫЛКУ, она отлично сериализуется
КонецЕсли;
Возврат Документы.ДопУслуга.ПустаяСсылка();
КонецФункции
Важный нюанс: Обратите внимание на использование директивы &НаСервереБезКонтекста. Это ускоряет работу, так как при вызове функции на сервер не передаются данные текущей формы (весь огромный объект ЭтаФорма).
Теперь, когда мы получили ссылку, мы можем использовать стандартный метод ОткрытьФорму(). Чтобы открыть форму конкретного (уже существующего) документа, нам нужно передать структуру параметров, содержащую ключ Ключ со значением нашей ссылки.
Рассмотрим клиентский код в обработчике события:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Если Объект.СуммаДокумента = 0 Тогда
// Используем современный асинхронный метод вопроса (для новых платформ)
// Или стандартный Вопрос, если модальность разрешена
Режим = РежимДиалогаВопрос.ДаНет;
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеВопросаОбОплате", ЭтотОбъект);
ПоказатьВопрос(ОписаниеОповещения, "Не оплачены доп. услуги, оплатить сейчас?", Режим);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПослеВопросаОбОплате(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
СсылкаНаДокумент = НайтиДокументДопУслуги(Объект.ПринятоОт);
Если НЕ СсылкаНаДокумент.Пустая() Тогда
ПараметрыФормы = Новый Структура("Ключ", СсылкаНаДокумент);
ОткрытьФорму("Документ.ДопУслуга.Форма.ФормаДокумента", ПараметрыФормы);
Иначе
Сообщить("Документ по данному физ. лицу не найден!");
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию с методом ОткрытьФорму(). В управляемом приложении этот метод является основным. Его синтаксис:
ОткрытьФорму(ИмяФормы, Параметры, Владелец, Уникальность, Окно, НавигационнаяСсылка, ОписаниеОповещенияОЗакрытии, РежимОткрытияОкна)
Когда мы передаем в Параметры структуру вида Новый Структура("Ключ", НужнаяСсылка), платформа понимает, что не нужно создавать новый объект, а нужно прочитать данные из базы для указанной ссылки и отобразить их в форме.
В современных конфигурациях 1С (начиная с версии платформы 8.3.15+) рекомендуется отказываться от модальных окон (функции Вопрос(), Предупреждение()). Вместо них следует использовать методы ПоказатьВопрос() и ПоказатьПредупреждение(). Это связано с работой в веб-клиентах и обеспечением стабильности интерфейса. Как показано в примере выше, логика разделяется: сначала мы задаем вопрос, а затем в отдельной процедуре-оповещении (callback) обрабатываем ответ пользователя и выполняем поиск документа.
Для эффективной работы и исключения ошибок отображения типов придерживайтесь следующих правил:
ДокументСсылка, СправочникСсылка) — это легкие идентификаторы, которые прекрасно передаются между слоями системы.Запрос. Это стандарт профессиональной разработки.Пустая()).&НаСервереБезКонтекста там, где не требуется обращение к реквизитам текущей экранной формы.Следуя этим рекомендациям, вы не только исправите ошибку Отсутствует отображение для типа, но и значительно повысите производительность и надежность вашего программного кода в 1С.