Разработка и Конфигурация · 11 мин
НаСервереБезКонтекста в 1С: для чего нужна и как применять
Разбираем директиву НаСервереБезКонтекста в 1С: зачем нужна, чем отличается от НаСервере, когда применять, типичные ошибки и проверка результата.
Директива &НаСервереБезКонтекста в управляемых формах 1С указывает, что процедура или функция выполняется на сервере, но при этом ей недоступен контекст формы: данные реквизитов, элементы формы, объект формы. На первый взгляд это выглядит как ограничение, но именно оно делает такие вызовы быстрее и дешевле по ресурсам, чем обычные серверные методы формы.
Проблема, которую решает директива, связана с устройством управляемых форм. Клиент и сервер в 1С — это разные процессы, часто на разных машинах. Каждый вызов сервера из формы с контекстом заставляет платформу сериализовать данные формы, передать их на сервер, собрать там контекст, выполнить код и вернуть изменения обратно. Если методу нужны только несколько параметров — например, ссылка на документ и дата — передача всего контекста формы становится лишней работой.
Понимание разницы между &НаСервере и &НаСервереБезКонтекста напрямую влияет на скорость работы форм, особенно в клиент-серверном варианте и при медленных каналах связи. Ниже разберём, как устроен механизм, когда какая директива уместна и какие ошибки встречаются чаще всего.
Как устроен вызов сервера из управляемой формы
В управляемой форме код делится на клиентскую и серверную части. Клиент работает в тонком или веб-клиенте, сервер — на сервере 1С:Предприятия. Когда из клиентской процедуры вызывается серверная, платформа выполняет удалённый вызов: упаковывает данные, передаёт по сети, исполняет код и возвращает результат.
Для методов с директивой &НаСервере платформа дополнительно передаёт весь контекст формы: значения реквизитов, состояние табличных частей, данные объекта. На сервере форма фактически воссоздаётся, метод работает с ней как с обычным объектом, после чего изменения упаковываются и уходят обратно клиенту. Чем больше данных в форме — списки, табличные части, динамические списки — тем тяжелее такой обмен.
Директива &НаСервереБезКонтекста отключает этот механизм. На сервер уходят только явно указанные параметры метода, а сам метод работает как обычная серверная процедура без привязки к форме. Если параметры — примитивные типы или ссылки, объём передаваемых данных минимален.
Чем НаСервереБезКонтекста отличается от НаСервере
Ключевое отличие — доступ к данным формы. В методе &НаСервере можно обратиться к реквизиту формы напрямую, изменить табличную часть, работать с объектом через РеквизитФормыВЗначение(). В методе без контекста всё это недоступно: попытка обратиться к реквизиту формы вызовет ошибку компиляции модуля.
Второе отличие — стоимость вызова. Передача контекста формы с крупной табличной частью или динамическим списком может занимать заметное время и генерировать трафик между клиентом и сервером. Вызов без контекста передаёт только параметры и возвращаемое значение, поэтому выполняется быстрее, особенно при частых вызовах.
| Критерий | НаСервере | НаСервереБезКонтекста |
|---|---|---|
| Доступ к реквизитам формы | Есть | Нет |
| Доступ к элементам формы | Есть | Нет |
| РеквизитФормыВЗначение() | Доступен | Недоступен |
| Передача контекста по сети | Полная сериализация формы | Только параметры метода |
| Типичное применение | Изменение данных формы на сервере | Получение данных из БД, расчёты, проверки |
Когда применять директиву
Основной сценарий — получение данных из базы, которые не требуют изменения формы в момент вызова. Например: узнать остаток товара по выбранной номенклатуре, получить цену из регистра сведений, проверить существование связанного документа, рассчитать значение по алгоритму. Клиент передаёт ссылку или набор значений, сервер возвращает результат.
Второй сценарий — вспомогательные функции, которые логически относятся к форме, но работают только с параметрами: форматирование данных, проверка условий, обращение к функциональным опциям или настройкам. Такие методы удобно держать в модуле формы рядом с местом использования, а не выносить в общий модуль.
Как выбрать директиву
Ограничения и подводные камни
Главное ограничение уже названо: никакого доступа к контексту формы. Если внутри метода без контекста внезапно понадобился реквизит формы, придётся либо передавать его значение параметром, либо менять директиву на &НаСервере. Попытка «обойти» ограничение через глобальные переменные или параметры сеанса — плохая практика, усложняющая сопровождение.
Второй момент — передаваемые параметры должны быть сериализуемыми. Ссылки, примитивные типы, структуры и массивы из них передаются без проблем. А вот объекты типа ДанныеФормыСтруктура, элементы формы или несериализуемые значения передать нельзя. Если нужно передать набор данных формы, соберите их в структуру на клиенте и передайте её.
Третий нюанс — изменения, сделанные на сервере, не отражаются в форме автоматически. Если метод без контекста записал что-то в базу, форма об этом не узнает: данные нужно вернуть через возвращаемое значение и обработать на клиенте, либо обновить форму явно.
Пример практической реализации
Типовая задача: при выборе номенклатуры в документе показать текущий остаток и цену. Клиентская процедура получает ссылку и вызывает серверный метод без контекста, который одним запросом забирает нужные данные и возвращает структуру.
&НаКлиенте
Процедура НоменклатураПриИзменении(Элемент)
Инфо = ПолучитьДанныеНоменклатуры(Объект.Номенклатура);
Остаток = Инфо.Остаток;
Цена = Инфо.Цена;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПолучитьДанныеНоменклатуры(НоменклатураСсылка)
Результат = Новый Структура("Остаток, Цена", 0, 0);
// запрос к регистрам остатков и цен
Возврат Результат;
КонецФункцииОбратите внимание: серверная функция не трогает форму — она получает ссылку и возвращает структуру. Клиент сам решает, куда подставить значения. Такой код легко тестировать, переносить в общий модуль и вызывать из других мест.
- 1Проверьте тело метода: нет ли обращений к реквизитам, элементам формы, РеквизитФормыВЗначение()
- 2Все нужные данные формы добавьте в сигнатуру метода как параметры (лучше структурой)
- 3Смените директиву на &НаСервереБезКонтекста и убедитесь, что модуль компилируется без ошибок
- 4Проверьте места вызова: клиентский код должен передавать параметры и обрабатывать возвращаемое значение
- 5Протестируйте сценарий в тонком клиенте и убедитесь, что данные в форме обновляются как ожидалось
Типичные ошибки и как их избежать
Самая частая ошибка — обращение к реквизиту формы внутри метода без контекста. Модуль не скомпилируется, и разработчик либо возвращает директиву &НаСервере, либо начинает передавать десяток параметров по одному. Правильнее оформить данные в структуру на клиенте — так сигнатура останется читаемой.
Вторая ошибка — ожидание, что изменения в базе данных сразу видны в форме. Метод без контекста записал документ, а форма продолжает показывать старые данные. Решение — вернуть признак успеха на клиент и там вызвать обновление данных или оповещение других форм через Оповестить().
Третья ошибка — перенос в метод без контекста логики, которая на самом деле нужна многим формам. Если одна и та же функция копируется в три формы, её место в общем серверном модуле. Методы формы без контекста оправданы, когда логика специфична именно для этой формы.
Проверка результата и влияние на производительность
Убедиться, что оптимизация сработала, можно через технологический журнал или замер времени вызова до и после смены директивы. В формах с тяжёлым контекстом — большими табличными частями, динамическими списками — разница между вызовом с контекстом и без него заметна невооружённым глазом, особенно в клиент-серверном режиме.
Дополнительный признак правильной работы — отсутствие лишних серверных вызовов. Откройте форму в тонком клиенте, выполните типовые действия и посчитайте обращения к серверу: их число не должно расти при рутинных операциях вроде перехода между полями.
Как проверить результат
Модуль компилируется, ошибок обращения к контексту нет
Ошибки вида «Переменная не определена» на реквизиты формы
Клиент получает возвращаемое значение и обновляет нужные поля
Данные на форме не меняются, хотя на сервере операция выполнилась
Один вызов на логическую операцию
Вызовы идут в цикле или на каждое изменение поля
Частые вопросы
Можно ли вызвать метод НаСервереБезКонтекста из клиентской процедуры?
Да, именно так он и используется. Из процедуры с директивой &НаКлиенте серверный метод без контекста вызывается напрямую по имени, как обычная функция. Платформа сама выполнит удалённый вызов и вернёт результат.
Что быстрее: НаСервереБезКонтекста или обращение к общему модулю?
По стоимости вызова они сопоставимы: и там, и там контекст формы не передаётся. Разница в организации кода: метод формы удобен для логики, привязанной к конкретной форме, общий модуль — для переиспользуемых функций.
Почему метод без контекста не видит реквизит формы, хотя он объявлен?
Это штатное поведение, а не ошибка платформы. Директива специально исключает контекст формы из вызова. Передайте нужное значение параметром или смените директиву на &НаСервере, если доступ к форме действительно необходим.
Можно ли передать таблицу значений в метод без контекста?
Таблицу значений напрямую передать нельзя — она не сериализуется между клиентом и сервером. Преобразуйте данные в массив структур на клиенте, передайте его, а на сервере при необходимости соберите таблицу обратно.
Нужна ли директива, если вся логика уже в общих модулях?
Если форма только вызывает общие модули и не имеет собственных серверных методов, директива в модуле формы не нужна. Она актуальна, когда серверный код логически принадлежит форме и держать его рядом с обработчиками удобнее.
Что важно запомнить
НаСервереБезКонтекста — это серверный вызов без передачи контекста формы: быстрее и легче, но без доступа к реквизитам и элементам. Применяйте директиву для получения данных из базы по параметрам, передавайте данные структурами, не вызывайте сервер в циклах и не забывайте обновлять форму на клиенте после изменений в базе.