Почему метод Web-сервиса 1С некорректно обрабатывает дату, передаваемую из PowerShell через New-WebServiceProxy?

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

При интеграции 1С с внешними системами часто используется механизм Web-сервисов (SOAP). Распространенный сценарий — вызов операций веб-сервиса из скриптов PowerShell с помощью командлета New-WebServiceProxy. Однако иногда разработчики и системные администраторы сталкиваются с ситуацией, когда вызов метода с динамически сформированной датой возвращает пустой или некорректный результат, в то время как при передаче жестко заданной строки (например, '03.10.2017') всё работает исправно.

Рассмотрим подробно причины возникновения этой проблемы и разберем варианты ее решения как на стороне PowerShell, так и в конфигурации 1С.

Анализ ситуации и поиск причины сбоя

Проанализируем исходный код вызова веб-сервиса в PowerShell:


$svc = New-WebServiceProxy –Uri 'http://server/base/ws/PersonnelData?wsdl'
$currDate = (Get-Date -DisplayHint Date -Format dd.MM.yyyy).ToString()
$UserArray = $svc.ReadStaffTable($currDate)

В данном примере выполняется получение текущей даты в формате dd.MM.yyyy с последующей передачей переменной $currDate в метод ReadStaffTable.

Выясним, что происходит на стороне 1С. В конфигураторе в дереве метаданных у веб-сервиса PersonnelData для операции ReadStaffTable установлен параметр QueryData с типом данных string (строка). В модуле веб-сервиса обработка входящего параметра выглядит следующим образом:


Функция ReadStaffTable(QueryData) Экспорт
    ДатаЗапроса = СтрокаВДату("dd.MM.yyyy", СтруктураПараметровОперацийWebСервисов.QueryData);
    // Дальнейшее формирование выборки данных
КонецФункции

Функция ожидает строго определенный формат строки с точками в качестве разделителей: 03.10.2017. Если строка не соответствует шаблону dd.MM.yyyy, алгоритм сбросит значение ДатаЗапроса в пустую дату ('0001-01-01'), и запрос к базе данных вернет некорректные результаты.

Влияние региональных настроек .NET и PowerShell

Почему же динамически сформированное значение $currDate перестает работать, а строка '03.10.2017' отрабатывает успешно?

Причина кроется в особенностях работы среды .NET Framework, на которой базируется PowerShell. В строках форматирования .NET символ точки . является не буквальным символом, а специальным управляющим символом разделителя дат (DateSeparator).

Если скрипт PowerShell выполняется на сервере с англоязычной локалью (например, en-US), .NET автоматически заменяет точку на разделитель, принятый в этой системной культуре — символ слэша /. В результате выражение (Get-Date -Format "dd.MM.yyyy").ToString() возвращает строку "03/10/2017" вместо "03.10.2017".

Когда эта строка поступает в 1С, вызов СтрокаВДату("dd.MM.yyyy", ...) не может разобрать дату со слэшами и сбрасывает ее в пустую. При передаче строкового литерала '03.10.2017' механизм форматирования .NET не задействуется, и строки передаются с точками напрямую.

Способы решения проблемы в PowerShell

Чтобы гарантировать передачу точек в строке даты независимо от локали операционной системы, рассмотрим несколько способов экранирования разделителя в PowerShell.

Способ 1. Экранирование символа разделителя кавычками

Заключим точки в одинарные кавычки внутри управляющей строки формата. В этом случае .NET воспримет их как буквальные символы:


$currDate = (Get-Date).ToString("dd'.'MM'.'yyyy")
$UserArray = $svc.ReadStaffTable($currDate)

Способ 2. Использование инвариантной культуры (InvariantCulture)

Форматирование с явно указанной нейтральной культурой исключает влияние региональных настроек Windows:


$currDate = (Get-Date).ToString("dd.MM.yyyy", [System.Globalization.CultureInfo]::InvariantCulture)
$UserArray = $svc.ReadStaffTable($currDate)

Способ 3. Явное приведение типа переменной

Для предотвращения передачи сложных объектов в SOAP-запрос укажем тип [string] при объявлении переменной:


[string]$currDate = (Get-Date).ToString("dd'.'MM'.'yyyy")
$UserArray = $svc.ReadStaffTable($currDate)

Рекомендации по проектированию Web-сервисов в 1С

Разберем, как сделать работу Web-сервисов более надежной на стороне платформы 1С:

  1. Использование стандартизированных типов данных. Вместо типа string для параметров, содержащих дату, рекомендуется задавать стандартный тип XML Schema date (xs:date) в свойствах операции Web-сервиса. В этом случае платформы 1С и .NET автоматически берут на себя сериализацию в формат ISO (yyyy-MM-dd).
  2. Переход на HTTP-сервисы (REST API). При проектировании новых интеграционных решений предпочтительнее использовать HTTP-сервисы 1С с обменом в формате JSON. Это избавляет от проблем с разделителями и упрощает отладку вызовов из PowerShell через командлет Invoke-RestMethod.
← На главную