Как обновить объект в 1С через REST API (OData) за один HTTP-запрос, не зная его GUID?

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

При работе со стандартным REST-интерфейсом OData в 1С:Предприятии часто возникает необходимость найти и обновить конкретную запись по значению реквизита (например, по коду, артикулу или ИНН). Попытка отправить модифицирующий HTTP-запрос (PATCH или PUT) с параметрами фильтрации $filter напрямую на URL коллекции приводит к ошибке с кодом 19: "Использованный HTTP метод запрещен в данном контексте" (HTTP status 405).

Проанализируем архитектурные ограничения платформы 1С и разберем практические способы решения этой задачи.

Причины возникновения ошибки и технические ограничения OData в 1С

Выясним, почему платформа не позволяет модифицировать данные по фильтру за один HTTP-вызов:

  1. Требование канонического URL: Спецификация OData и реализация REST-интерфейса в 1С требуют, чтобы операции изменения (PATCH, PUT, DELETE) адресовались строго конкретному экземпляру сущности по его каноническому URL. Для справочников и документов этот адрес обязательно содержит первичный ключ — уникальный идентификатор guid'...'.
  2. Назначение параметров фильтрации: Параметры $filter, $top и $orderby предназначены только для операций чтения (GET) над коллекциями сущностей. Маршрутизатор 1С блокирует попытки передачи методов изменения на адрес всей коллекции.
  3. Отсутствие поддержки $batch для поиска с записью: В отличие от некоторых сторонних реализаций OData, стандартный сервис 1С не поддерживает сложные операции типа Upsert по произвольным реквизитам в рамках единого URL.

Способ 1. Оптимизированный двухэтапный подход (без изменения конфигурации)

Если информационная база находится на типовой поддержке и её нельзя модифицировать, единственным штатным решением является последовательное выполнение двух HTTP-запросов. Чтобы свести к минимуму нагрузку на веб-сервер и СУБД, проанализируем, как правильно оптимизировать первый запрос чтения.

Шаг 1. Легковесный GET-запрос для получения GUID:

Запрашиваем исключительно ключ ссылки Ref_Key, передавая фильтр и ограничение на количество записей. Вызов параметра $select=Ref_Key предписывает платформе считывать только идентификатор объекта, игнорируя остальные реквизиты и табличные части.

Пример HTTP GET-запроса:

GET /base/odata/standard.odata/Catalog_Контрагенты?$filter=Code eq '000000001'&$select=Ref_Key&$top=1&$format=json

В ответе от сервера получаем структуры с нужным GUID:


{
    "odata.metadata": "http://server/base/odata/standard.odata/$metadata#Catalog_Контрагенты/$entity",
    "Ref_Key": "e1c8e182-1234-11e8-80c7-005056c00008"
}

Шаг 2. Модификация объекта через PATCH:

Используя полученный Ref_Key, формируем канонический URL элемента и отправляем запрос на частичное изменение данных.

Пример HTTP PATCH-запроса:

PATCH /base/odata/standard.odata/Catalog_Контрагенты(guid'e1c8e182-1234-11e8-80c7-005056c00008')?$format=json

В теле запроса передаем только те свойства, которые необходимо обновить:


{
    "Комментарий": "Обновлено через REST API"
}

Способ 2. Создание собственного HTTP-сервиса (один запрос)

Если условием интеграции является выполнение операции строго за один HTTP-запрос, оптимальным решением станет разработка собственного HTTP-сервиса. Чтобы не снимать конфигурацию с поддержки, создадим расширение конфигурации.

Рассмотрим порядок действий при таком подходе:

  1. Подключим к информационной базе расширение конфигурации.
  2. Добавим в расширение объект HTTP-сервис (назовем его, например, ОбновлениеОбъектов) с корневым URL /update.
  3. Создадим шаблон URL /by-code и метод POST (или PATCH) с обработчиком в модуле HTTP-сервиса.

Пример кода обработчика HTTP-запроса в 1С:


Функция ПостПоискаИОбновления(Запрос)
    
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(Запрос.ПолучитьТелоКакСтроку());
    ДанныеЗапроса = ПрочитатьJSON(ЧтениеJSON);
    ЧтениеJSON.Закрыть();
    
    КодОбъекта = ДанныеЗапроса.Код;
    НовыйКомментарий = ДанныеЗапроса.Комментарий;
    
    // Поиск объекта в базе данных
    СсылкаНаОбъект = Справочники.Контрагенты.НайтиПоКоду(КодОбъекта);
    
    Если СсылкаНаОбъект.Пустая() Тогда
        Ответ = Новый HTTPСервисОтвет(404);
        Возврат Ответ;
    КонецЕсли;
    
    // Обновление реквизитов объекта
    Попытка
        ОбъектБД = СсылкаНаОбъект.ПолучитьОбъект();
        ОбъектБД.Комментарий = НовыйКомментарий;
        ОбъектБД.Записать();
        
        Ответ = Новый HTTPСервисОтвет(200);
        Ответ.УстановитьТелоИзСтроки("Text updated successfully");
    Исключение
        Ответ = Новый HTTPСервисОтвет(500);
        Ответ.УстановитьТелоИзСтроки(ОписаниеОшибки());
    КонецПопытки;
    
    Возврат Ответ;
    
КонецФункции

В результате внешний клиент сможет отправить ровно один HTTP-запрос на адрес собственного сервиса и обновить данные объекта без знания его Ref_Key.

Специфика работы с регистрами сведений

Обратим внимание на работу с регистрами сведений. В отличие от справочников и документов, записи независимых или периодических регистров сведений не имеют ссылок типа GUID. В OData канонический URL записи регистра формируется из значений ключевых измерений и даты периода.

В этом случае знание GUID не требуется — обновлять или записывать данные через PUT/PATCH можно сразу за один запрос, если известны значения всех ключевых полей измерения:

PUT /base/odata/standard.odata/InformationRegister_ЦеныНоменклатуры(Period=datetime'2023-01-01T00:00:00', Номенклатура_Key=guid'...')

← На главную