Какие значения управляемая форма 1С отправляет на сервер, а какие нет

· 9 мин

Содержание

С клиента на сервер в 1С 8.3 можно передавать только значения, которые существуют в обоих контекстах и умеют сериализоваться: примитивы (Число, Строка, Дата, Булево, Неопределено, Null), ссылки на объекты базы, значения перечислений, Структура, Массив, Соответствие, СписокЗначений, ДвоичныеДанные, УникальныйИдентификатор, ОписаниеТипов и данные формы. Коллекции передаются, только если внутри у них тоже лежат передаваемые значения.

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

Как устроены два контекста управляемого приложения

В управляемом приложении код формы выполняется в двух местах. Тонкий клиент или веб-клиент рисует форму и реагирует на действия пользователя. Сервер 1С:Предприятия работает с базой данных: читает, пишет, проводит.

Каждая процедура модуля формы помечается директивой компиляции:

  • 🖥️ &НаКлиенте — выполняется на компьютере пользователя, базы не видит;
  • 🗄️ &НаСервере — выполняется на сервере, получает копию данных формы;
  • 📦 &НаСервереБезКонтекста — выполняется на сервере без данных формы, видит только свои параметры;
  • 🔀 &НаКлиентеНаСервереБезКонтекста — компилируется в обоих местах, работает только с тем, что доступно везде.

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

Из общих модулей с клиента доступны только серверные модули с флагом «Вызов сервера». Модуль без этого флага клиентский код просто не видит: при проверке модуля платформа сообщит, что переменная с именем модуля не определена.

Какие типы данных проходят между клиентом и сервером

Общее правило простое: тип должен быть доступен и на клиенте, и на сервере. В синтакс-помощнике это видно в разделе «Доступность» у каждого типа. Если там нет тонкого клиента — значение до клиента не доедет, и обратно тоже.

ГруппаТипыОсобенности
ПримитивыЧисло, Строка, Дата, Булево, Неопределено, NullПередаются всегда
СсылкиСправочникСсылка.*, ДокументСсылка.*, ПеречислениеСсылка.*, ссылки на ПВХ, планы счетовУходит только ссылка, без реквизитов объекта
Универсальные коллекцииСтруктура, Массив, Соответствие, СписокЗначений и их фиксированные вариантыВсе элементы тоже должны быть передаваемыми
СлужебныеУникальныйИдентификатор, ОписаниеТипов, Тип, ДвоичныеДанные, СтандартныйПериодПодходят для ключей и параметров
ОформлениеТабличныйДокумент, ФорматированнаяСтрока, Картинка, Цвет, ШрифтТипично для печатных форм и отчётов
Данные формыДанныеФормыСтруктура, ДанныеФормыКоллекция, ДанныеФормыДеревоКлиентское представление объектов, таблиц и деревьев

Ссылка — самый удобный способ указать серверу на объект. Клиент не знает реквизитов справочника, но ссылку держит спокойно. Сервер по ней прочитает всё, что нужно.

Пример: клиент передаёт ссылку на контрагента и получает структуру с нужными полями.

&НаКлиенте
Процедура КонтрагентПриИзменении(Элемент)
	Сведения = СведенияОКонтрагенте(Объект.Контрагент);
	Объект.ИНН = Сведения.ИНН;
	Объект.КПП = Сведения.КПП;
КонецПроцедуры

&НаСервереБезКонтекста
Функция СведенияОКонтрагенте(Знач Контрагент)
	Результат = Новый Структура("ИНН, КПП", "", "");
	Если ЗначениеЗаполнено(Контрагент) Тогда
		ЗаполнитьЗначенияСвойств(Результат, Контрагент);
	КонецЕсли;
	Возврат Результат;
КонецФункции

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

Что передать нельзя и как обойти запрет

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

Только серверные — на клиент не вернуть:

  • ❌ ТаблицаЗначений и ДеревоЗначений;
  • ❌ Запрос, РезультатЗапроса, выборки, МенеджерВременныхТаблиц;
  • ❌ объекты: СправочникОбъект, ДокументОбъект, НаборЗаписей, МенеджерЗаписи;
  • ❌ схема компоновки данных и прочие серверные механизмы.

Только клиентские — на сервер не отправить:

  • ❌ сама форма (ЭтотОбъект в модуле формы) — в &НаСервереБезКонтекста её не передать;
  • ❌ ОписаниеОповещения — живёт только на клиенте;
  • ❌ COMОбъект, созданный на клиенте;
  • ❌ элементы формы (Элементы.Список и т. п.).

Ловушка с коллекциями: Структура сама по себе передаётся, но если положить в неё ТаблицаЗначений, вызов упадёт. Платформа проверяет содержимое целиком, на любую глубину вложенности.

Как обойти запрет:

Что нужно передатьЧем заменитьКогда подходит
Объект справочника или документаСсылку, а на сервере Ссылка.ПолучитьОбъект()Почти всегда
Таблицу значений, небольшуюМассив из Структура, по одной на строкуДо нескольких сотен строк
Таблицу значений для формыРеквизит формы типа ТаблицаЗначений и ЗначениеВРеквизитФормы()Таблицу надо показать пользователю
Большой объём данных, файлВременное хранилище и его адрес-строкуФайлы, выгрузки, тяжёлые отчёты
Результат запросаМассив ссылок или структур, собранный на сервереКлиенту нужен только список

В БСП для таблиц есть готовая функция ОбщегоНазначения.ТаблицаЗначенийВМассив: она превращает таблицу в массив структур, который спокойно уходит на клиент.

Как передаются параметры и данные формы при серверном вызове

Здесь кроется главная разница между &НаСервере и &НаСервереБезКонтекста.

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

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

Отдельный момент — модификатор Знач:

  1. Параметр без Знач передаётся по ссылке. После серверного вызова его значение возвращается на клиент, даже если сервер его не менял.
  2. Параметр с Знач уходит только в одну сторону. Обратно его копия не возвращается.
  3. Для серверных процедур, которые не должны менять параметр, ставьте Знач. Это экономит трафик, особенно если параметр — большая структура или массив.

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

Внутри &НаСервере с данными формы работают через специальные методы:

  • 🔄 РеквизитФормыВЗначение("Объект") — получить настоящий ДокументОбъект или СправочникОбъект из данных формы;
  • 🔄 ЗначениеВРеквизитФормы(ДокОбъект, "Объект") — положить объект обратно в форму;
  • 🔄 ДанныеФормыВЗначение() и ЗначениеВДанныеФормы() — то же для произвольных значений и коллекций.

Эти методы есть только на сервере. На клиенте форма видит лишь ДанныеФормыСтруктура и ДанныеФормыКоллекция — урезанные копии без методов записи и проведения.

Глобальный контекст: что доступно на клиенте, а что на сервере

Многие свойства и методы глобального контекста привязаны к одной стороне. Ошибка «метод недоступен на клиенте» — частый спутник переноса кода из обычных форм в управляемые.

ЗадачаНа клиентеНа сервере
Получить предопределённое значениеПредопределенноеЗначение("Справочник.Валюты.Рубль")Можно и так, и через менеджер Справочники.Валюты.Рубль
Спросить пользователяПоказатьВопрос, ПоказатьПредупреждениеНедоступно
Сообщить пользователюСообщение с Новый СообщениеПользователюТоже работает: сообщение доедет до клиента
Параметры сеансаНапрямую недоступныПараметрыСеанса.Имя
Хранить значения на время сеансаГлобальная ПараметрыПриложения (Соответствие)Модули повторного использования, параметры сеанса
Открыть формуОткрытьФормуНедоступно

Менеджеры объектов (Справочники, Документы, Перечисления) на тонком клиенте недоступны. Поэтому на клиенте пустую ссылку или предопределённый элемент берут через ПредопределенноеЗначение, а не через Справочники.Валюты.ПустаяСсылка().

Для общих утилит удобно разделение модулей:

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

Как сократить число вызовов и защитить данные

Каждый серверный вызов — это сетевой круг. На локальной сети он незаметен. На медленном канале, VPN или веб-клиенте десять вызовов в обработчике превращаются в заметную задержку.

Что реально помогает:

  1. Собирать данные одним вызовом. Вместо трёх функций «получить ИНН», «получить КПП», «получить адрес» — одна, которая возвращает структуру.
  2. Предпочитать &НаСервереБезКонтекста. Контекстный вызов нужен, только если серверу правда нужны данные формы.
  3. Ставить Знач у параметров, которые сервер не меняет.
  4. Кэшировать редко меняющееся. Серверный общий модуль с повторным использованием «На время сеанса» вызывается с клиента один раз, дальше клиент берёт результат из кэша. Возвращайте из таких модулей фиксированные коллекции (ФиксированнаяСтруктура, ФиксированныйМассив), чтобы результат никто случайно не изменил.
  5. Не таскать файлы через параметры. Помещайте их во временное хранилище: на клиенте — методами помещения файлов, на сервере — ПоместитьВоВременноеХранилище(). Передавайте только адрес.

Проверить, сколько вызовов делает форма, можно замером производительности в режиме отладки: в Конфигураторе это Отладка → Замер производительности. В результатах видно, какие серверные процедуры вызываются и сколько раз.

С безопасностью правило одно: сервер не доверяет ничему, что пришло с клиента. Модуль с флагом «Вызов сервера» — это открытая дверь, через которую можно передать любые значения.

  • 🔒 проверяйте права на сервере, а не скрытием кнопок на форме;
  • 🔒 проверяйте тип и заполненность параметров в начале серверной функции;
  • 🔒 привилегированный режим включайте только на сервере и только внутри модуля без флага «Вызов сервера»;
  • 🔒 не возвращайте на клиент пароли, токены и персональные данные сверх необходимого.

Не делайте общий модуль одновременно «Привилегированным» и «Вызов сервера». Тогда любой пользователь сможет вызвать его функции с любыми параметрами в обход своих прав.

Ошибки при передаче значений и что с ними делать

Почти все проблемы на этой границе сводятся к нескольким сценариям. Ниже — симптомы и куда смотреть.

Диагностика: выберите симптом

Частые вопросы

Можно ли передать на сервер табличную часть документа из формы?
Да. В контекстном вызове &НаСервере она уже есть в Объект. В вызов без контекста её можно передать параметром: на клиенте это ДанныеФормыКоллекция, она передаваемая.
Почему структура не передаётся, хотя тип Структура допустим?
Платформа проверяет всё содержимое. Если хотя бы одно значение внутри — таблица, объект или запрос, вызов упадёт. Найдите это поле и замените его.
Передаётся ли вместе со ссылкой весь объект?
Нет. Уходит только ссылка. Обращение к её реквизитам на клиенте не работает, их читают на сервере.
Можно ли вызвать сервер из процедуры &НаКлиентеНаСервереБезКонтекста?
Можно, если вызываемая функция доступна в обоих контекстах, например лежит в серверном модуле с флагом «Вызов сервера». На сервере такой вызов станет обычным, на клиенте — серверным.
Что выгоднее для передачи сотни строк: массив структур или временное хранилище?
Для сотен строк хватит массива структур. Хранилище оправдано для файлов, двоичных данных и выгрузок на десятки тысяч строк, когда данные нужны не сразу.