Как определить тип клиента в процедуре ПередЗаписьюНаСервере в 1С 8.3?

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

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

Анализ причины: почему препроцессор не работает на сервере

Рассмотрим ситуацию, описанную автором темы. В коде процедуры ПередЗаписьюНаСервере используется конструкция:


#Если ВебКлиент Тогда
    Сообщить("Это Веб Клиент");
#Иначе
    Сообщить("Это не Веб Клиент!");
#КонецЕсли

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

Выясним, как программа может «понять», какой именно клиент инициировал вызов серверной процедуры, если стандартные инструкции препроцессора здесь бесполезны.

Способ 1: Использование функции ИмяПриложения()

Проанализируем наиболее изящный способ определения типа клиента непосредственно в серверном коде. В глобальном контексте 1С существует функция ИмяПриложения(). Она доступна на сервере и возвращает строковое значение, идентифицирующее тип клиентского приложения, которое обратилось к серверу в данный момент.

Рассмотрим пример реализации:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    ТипПриложения = ИмяПриложения();
    
    Если ТипПриложения = "WebClient" Тогда
        // Здесь логика специально для браузера
        Сообщить("Запись инициирована из Веб-клиента");
    ИначеЕсли ТипПриложения = "1CV8C" Тогда
        // Логика для тонкого клиента
        Сообщить("Запись инициирована из Тонкого клиента");
    КонецЕсли;

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

Этот метод хорош тем, что он не требует передачи дополнительных данных с клиента на сервер и работает максимально быстро. Функция ИмяПриложения() может возвращать следующие значения:

Способ 2: Передача признака через ПараметрыЗаписи

Иногда требуется более сложная логика, которую проще определить еще на этапе нахождения «на клиенте». В процедуре ПередЗаписью на клиенте у нас есть доступ к структуре ПараметрыЗаписи. Все данные, добавленные в эту структуру, автоматически доставляются в серверную процедуру ПередЗаписьюНаСервере.

Разберем этот метод по шагам:

  1. В клиентской процедуре определим тип клиента с помощью препроцессора и поместим результат в параметры.
  2. На сервере извлечем это значение.

Пример кода на клиенте:


&НаКлиенте
Процедура ПередЗаписью(Отказ, ПараметрыЗаписи)
    
    #Если ВебКлиент Тогда
        ПараметрыЗаписи.Вставить("ЭтоВебКлиент", Истина);
    #Иначе
        ПараметрыЗаписи.Вставить("ЭтоВебКлиент", Ложь);
    #КонецЕсли
    
КонецПроцедуры

Пример кода на сервере:


&НаСервере
Процедура ПередЗаписьюНаСервере(Отказ, ТекущийОбъект, ПараметрыЗаписи)
    
    ЭтоВеб = Ложь;
    Если ПараметрыЗаписи.Свойство("ЭтоВебКлиент", ЭтоВеб) Тогда
        Если ЭтоВеб Тогда
            // Выполняем действия для веб-клиента
        КонецЕсли;
    КонецЕсли;
    
КонецПроцедуры

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

Способ 3: Использование параметров сеанса

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

Посмотрим, как это реализовать. В дереве конфигурации создадим параметр сеанса ТекущийТипКлиента (тип: Строка или Перечисление). В модуле сеанса, в процедуре УстановкаПараметровСеанса, пропишем логику инициализации. После этого в любой серверной процедуре (включая ПередЗаписьюНаСервере) вы сможете просто обращаться к ПараметрыСеанса.ТекущийТипКлиента без лишних вычислений.

Важные нюансы и ограничения

При работе в процедуре ПередЗаписьюНаСервере необходимо помнить о нескольких критически важных моментах:

Интерактивные действия: На сервере категорически нельзя использовать методы, требующие ответа пользователя, такие как Вопрос() или Предупреждение(). Если ваша логика в зависимости от типа клиента должна задать вопрос пользователю, это нужно делать строго в клиентской процедуре ПередЗаписью.

Особенности Сообщить(): Использование Сообщить() на сервере допустимо, но следует учитывать, что в веб-клиенте эти сообщения будут выведены пользователю только после того, как управление полностью вернется на сторону клиента. В некоторых случаях порядок вывода сообщений может отличаться от ожидаемого.

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

Подводя итог, можно сказать: чтобы программа «поняла», какой клиент используется, не пытайтесь использовать #Если на сервере. Используйте ИмяПриложения() для быстрой проверки или ПараметрыЗаписи для передачи флагов с клиента. Это обеспечит стабильную работу вашего кода как в тонком клиенте, так и в веб-интерфейсе.

← На главную