Как исправить ошибку «недостаточно фактических параметров» при обмене через Web-сервис в 1С?

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

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

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

Суть проблемы и анализ исходного кода

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


Функция ПолучитьОстаткиНоменклатуры(Код = Неопределено)
    Если Код = Неопределено Тогда
        Запрос = Новый Запрос;
        Запрос.Текст = "ВЫБРАТЬ
                       |    ЗапасыНаСкладахОстатки.Номенклатура.Код КАК НоменклатураКод,
                       |    ЗапасыНаСкладахОстатки.КоличествоОстаток КАК КоличествоОстаток
                       |ИЗ
                       |    РегистрНакопления.ЗапасыНаСкладах.Остатки(&Дата, ) КАК ЗапасыНаСкладахОстатки";
        Запрос.УстановитьПараметр("Дата", ТекущаяДата());
        РезультатЗапроса = Запрос.Выполнить().Выгрузить();
        Возврат Новый ХранилищеЗначения(РезультатЗапроса);
    Иначе
        // Логика получения остатков по конкретному коду
        // ...
    КонецЕсли;
КонецФункции

Программист рассчитывает на то, что раз в заголовке функции указано значение по умолчанию Код = Неопределено, то метод можно вызывать без аргументов. Однако при обращении через WSПрокси в регламентном задании платформа выбрасывает исключение. Выясним причину этого поведения.

Почему значения по умолчанию не работают в Web-сервисах?

Разберем важный нюанс: когда вы работаете с Web-сервисом, вы вызываете не просто функцию модуля, а операцию, описанную в WSDL (Web Services Description Language). WSDL — это жесткий контракт. Если в метаданных Web-сервиса в 1С у операции добавлен параметр Код, то в описании интерфейса этот параметр становится обязательным элементом структуры запроса.

Платформа 1С при создании прокси-объекта (WSProxy) строго следует этому контракту. Если в WSDL указано, что метод принимает один параметр, вы не можете вызвать его как Прокси.ПолучитьОстаткиНоменклатуры(). Это фундаментальное отличие от обычного вызова процедур и функций внутри конфигурации. Даже если вы установили свойство параметра «Возможно пустое значение» (nillable), это лишь означает, что вы можете передать в него NULL, но сам параметр в списке аргументов при вызове метода присутствовать обязан.

Способ 1. Явная передача пустого значения

Самое простое и быстрое решение — привести вызов в регламентном задании в соответствие с требованиями WSDL. Вместо вызова без параметров, необходимо явно передать Неопределено или пустое значение.

Проанализируем пример корректного вызова:


// В коде регламентного задания
Прокси = СформироватьWSПрокси(); // Ваша функция инициализации
// Вместо Прокси.ПолучитьОстаткиНоменклатуры() пишем:
ОстаткиХранилище = Прокси.ПолучитьОстаткиНоменклатуры(Неопределено);
Результат = ОстаткиХранилище.Получить();

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

Способ 2. Разделение методов (Лучшая практика)

Для чистоты архитектуры и избежания путаницы в параметрах, рассмотрим вариант создания двух разных методов в Web-сервисе. Это исключит неоднозначность при интерпретации параметров.

  1. Создайте метод ПолучитьВсеОстатки() без параметров.
  2. Создайте метод ПолучитьОстаткиПоНоменклатуре(Код) с обязательным параметром.

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

Способ 3. Использование служебных значений

Если вы не хотите менять структуру методов, можно использовать подход со «служебными маркерами». Это часто помогает, когда возникают сложности с типизацией Неопределено в SOAP-запросах.

Рассмотрим пример логики:


// На стороне клиента (регламентное задание)
СлужебныйКод = "ALL_ITEMS";
Результат = Прокси.ПолучитьОстаткиНоменклатуры(СлужебныйКод);

// На стороне сервера (Web-сервис)
Функция ПолучитьОстаткиНоменклатуры(Код)
    Если Код = "ALL_ITEMS" Или Код = "" Тогда
        // Запрос по всем позициям
    Иначе
        // Запрос по конкретному коду
    КонецЕсли;
КонецФункции

Нюансы кэширования и обновления WSDL

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

При вызове Web-сервиса через Новый WSОпределения(URL) платформа загружает описание сервиса. Если это описание закэшировалось в сеансе фонового задания, изменения в метаданных не будут подхвачены немедленно. Рекомендуется:

Использование XDTO для необязательных параметров

Если вы хотите реализовать действительно необязательный параметр (который можно вообще не передавать в XML-структуре), рассмотрим использование объектов XDTO. Для этого в пакете XDTO, который используется вашим Web-сервисом, у соответствующего свойства нужно установить значение Минимальное количество (minOccurs) = 0.

В этом случае, если свойство не заполнено, оно полностью исключается из XML-пакета. Однако для этого тип параметра операции Web-сервиса должен быть не примитивным (Строка, Число), а ссылаться на соответствующий ОбъектXDTO. Это более сложный, но профессиональный способ проектирования интерфейсов обмена.

Резюме

Основная причина ошибки заключается в том, что интерфейс Web-сервиса игнорирует значения по умолчанию, прописанные в коде 1С. Чтобы исправить проблему, всегда передавайте в WSПрокси столько аргументов, сколько описано в операции Web-сервиса, используя Неопределено или пустые значения для тех полей, которые не требуются для текущего запроса.

← На главную