К статье
Практический материал

Разработка и Конфигурация · 12 мин

Что значит «На сервере без контекста» в 1С: разбор на практике

Разбираем директиву «На сервере без контекста» в 1С: когда ставить, чем отличается от сервера с контекстом, ограничения, типичные ошибки и примеры кода.

Директива компиляции «На сервере без контекста» (в коде — &НаСервереБезКонтекста) встречается в управляемых формах 1С практически в каждой конфигурации. Она указывает платформе, что процедура или функция формы должна выполняться на сервере 1С:Предприятия, при этом форма не передаёт на сервер свои данные целиком. Понимание этого механизма напрямую влияет на быстродействие форм и на корректность кода: неправильно выбранная директива приводит либо к ошибкам компиляции, либо к лишнему трафику между клиентом и сервером.

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

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

Что такое контекст формы и почему от него «отказываются»

Контекст формы — это вся совокупность данных, связанных с открытой формой: реквизиты формы, данные основного реквизита (например, объекта документа), элементы управления, табличные части, настройки. Когда серверная процедура вызывается «с контекстом», платформа сериализует эти данные, передаёт их на сервер, выполняет код и возвращает изменённое состояние обратно на клиент.

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

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

Чем «НаСервереБезКонтекста» отличается от «НаСервере»

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

КритерийНаСервереНаСервереБезКонтекста
Место выполненияСервер 1ССервер 1С
Доступ к реквизитам формыЕстьНет
Доступ к элементам формыЕсть (через объект формы)Нет
Доступ к основному объектуЕстьТолько через переданную ссылку
Передача данных формы на серверПолная сериализацияНе выполняется
Скорость вызоваМедленнее при больших данныхБыстрее

Важный нюанс: в процедуре без контекста можно работать с базой данных напрямую — выполнять запросы, читать и записывать объекты по ссылке, вызывать серверные методы общих модулей. Недоступен именно интерфейсный контекст текущей формы.

Например, если нужно по ссылке на номенклатуру получить её цену, реквизиты или остаток — это типичная задача для процедуры без контекста. Ссылка передаётся параметром, запрос выполняется на сервере, результат возвращается клиенту.

Сравнение вариантов

НаСервереБезКонтекста

Подходит для чтения данных по ссылке, запросов, расчётов, вызова общих модулей. Ограничение: нет доступа к реквизитам и элементам формы.

НаСервере

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

Общий серверный модуль

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

Синтаксис и пример кода

Директива ставится перед объявлением процедуры или функции в модуле формы. Типичный пример — получение данных по ссылке без обращения к реквизитам формы:

&НаСервереБезКонтекста

Функция ПолучитьЦенуНоменклатуры(НоменклатураСсылка)

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Цены.Цена КАК Цена

|ИЗ

| РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, Номенклатура = &Номенклатура) КАК Цены";

Запрос.УстановитьПараметр("Номенклатура", НоменклатураСсылка);

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

Возврат Выборка.Цена;

КонецЕсли;

Возврат 0;

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

Вызов из клиентской процедуры выглядит обычно — платформа сама организует серверный вызов:

&НаКлиенте

Процедура НоменклатураПриИзменении(Элемент)

Цена = ПолучитьЦенуНоменклатуры(Объект.Номенклатура);

Объект.Цена = Цена;

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

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

Когда ставить «без контекста», а когда — «с контекстом»

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

Директиву &НаСервере оправданно использовать, когда нужно: заполнить или изменить табличную часть основного объекта сложным образом (например, массовый пересчёт строк с обращением к данным формы), программно изменить состав или свойства элементов формы, прочитать или изменить несколько реквизитов формы одним вызовом.

Ещё один сценарий для «с контекста» — преобразование данных формы в объект через РеквизитФормыВЗначение() и обратно, когда требуется полноценная работа с объектом (например, вызов его экспортных методов). Эта операция доступна только в серверном контексте формы.

Если же логика вообще не привязана к конкретной форме — выносите её в общий серверный модуль. Это лучше, чем копировать функции «без контекста» по десятку форм: общий модуль проще тестировать и поддерживать.

Маршрут решения

Как выбрать директиву

Нужно только прочитать данные по ссылке или выполнить запросИспользуйте &НаСервереБезКонтекста, ссылку передавайте параметром
Нужно изменить табличную часть основного объекта формыИспользуйте &НаСервере или обработку на клиенте с последующим серверным вызовом
Нужно программно менять элементы формы (видимость, состав)Используйте &НаСервере — без контекста элементы недоступны
Логика нужна в нескольких формахВынесите её в общий модуль с флагом Сервер
Метод объекта требуется вызвать целиком (Провести, Записать)Используйте &НаСервере с РеквизитФормыВЗначение или общий модуль

Ограничения режима «без контекста»

Главное ограничение уже названо: полное отсутствие доступа к контексту формы. Внутри такой процедуры нельзя обратиться к Объект, Элементы, реквизитам формы, командам формы. Компилятор выдаст ошибку вида «Переменная не определена».

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

Третий момент: каждый вызов серверной процедуры, даже без контекста, — это сетевой обмен. Если в цикле на клиенте вызывается серверная функция для каждой строки таблицы из тысячи строк, форма «повиснет». Правильный подход — собрать данные в массив или таблицу и передать на сервер одним вызовом.

Типичные ошибки и как их диагностировать

Первая и самая частая ошибка — обращение к реквизиту формы из процедуры без контекста. Код не компилируется, платформа сообщает, что переменная не определена. Лечение: передать нужное значение параметром из клиентской процедуры.

Вторая ошибка — передача на сервер несериализуемых данных. Например, попытка передать Элементы.ТабличнаяЧасть.ТекущиеДанные целиком. Такие данные нужно разобрать на клиенте и передать примитивы или структуру.

Третья ошибка — избыточное использование «с контекста» там, где достаточно «без контекста». Формально код работает, но каждый вызов тащит на сервер все данные формы. На больших документах это заметно тормозит работу пользователей. Симптом: форма «подтормаживает» при изменении полей, хотя запросы простые.

Четвёртая ошибка — забыть, что функция без контекста не может менять данные формы напрямую. Разработчик пишет серверную функцию, которая «заполняет» реквизит, а на клиенте ничего не меняется, потому что присвоение выполнено в отрыве от формы. Результат нужно возвращать и присваивать на клиенте.

Типичные ошибки
01
Обращение к Объект или Элементы внутри процедуры без контекста — ошибка компиляции «Переменная не определена»
02
Серверный вызов в цикле по строкам — сотни сетевых обменов, форма зависает
03
Использование &НаСервере там, где хватило бы без контекста — лишняя сериализация данных формы и медленная работа
04
Присвоение результата реквизиту формы на сервере — изменения не доходят до клиента, присваивать нужно на клиенте
05
Передача несериализуемых данных (элементы формы, ДанныеФормы) параметром — ошибка при вызове

Как проверить, что вызов устроен правильно

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

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

Контрольные точки

Как проверить результат

Компиляция модуля формы
Норма

Ошибок нет, все обращения к данным формы — только в процедурах с контекстом или на клиенте

Тревожный признак

Ошибки «Переменная не определена» в серверных процедурах

Количество серверных вызовов на действие
Норма

1–2 вызова, без вызовов внутри циклов

Тревожный признак

Десятки вызовов при одном изменении поля

Скорость реакции формы
Норма

Поля и таблицы обновляются без видимых пауз

Тревожный признак

Заметная задержка при каждом изменении

Актуальность данных на клиенте
Норма

После серверной функции результат присваивается реквизитам на клиенте

Тревожный признак

Сервер посчитал, а в форме ничего не изменилось

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

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

Можно ли из процедуры «без контекста» записать объект в базу?

Да. По переданной ссылке можно получить объект методом ПолучитьОбъект(), изменить его и записать. Ограничение касается только доступа к данным текущей формы, а не к базе данных. Однако учтите: изменения в базе не обновят автоматически данные открытой формы — их нужно перечитать или обновить на клиенте.

Почему код с директивой «без контекста» не видит реквизит формы?

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

Что быстрее: «НаСервере» или «НаСервереБезКонтекста»?

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

Можно ли вызвать процедуру без контекста с клиента напрямую?

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

Когда код лучше вынести в общий модуль вместо формы?

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

Работает ли «без контекста» в тонком и веб-клиенте?

Да, директива работает во всех клиентах управляемого приложения: толстом (в режиме управляемого приложения), тонком и веб-клиенте. Механизм серверного вызова одинаков, различается только канал связи клиента с сервером.

Итог

Что важно запомнить

«На сервере без контекста» — это серверное выполнение без передачи данных формы: быстрее и дешевле, но без доступа к реквизитам и элементам. Используйте эту директиву по умолчанию для чтения данных и расчётов, переходите на «НаСервере» только когда нужен контекст формы, а переиспользуемую логику выносите в общие модули. Избегайте серверных вызовов в циклах.