SharePoint List REST API. Часть 1

Основные операции по работе со списками и библиотеками документов описаны в статье Работа со списками и элементами списков с использованием REST. В этом посте я покажу как выполнять операции с большинством из существующих типов полей, таких как метаданные (Таксономия), множественный выбор, подстановка и другими.

Поля списка

Мой демонстрационный список содержит следующие поля:

Поля демонстрационного списка

Поля демонстрационного списка

Обязательным является только поле Title.

Перед тем как мы начнем работать с SharePoint REST API пара моментов о среде:

Простой AJAX запрос:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Accept": "application/json; charset=utf-8",
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val()
    }
});

Заголовок X-RequestDigest должен содержать допустимое значение дайджеста для каждого не-POST запроса (Работа с __REQUESTDIGEST).

Для получения REST url'а для списка можно использовать следующий код:

var url = _spPageContextInfo.webServerRelativeUrl + "_api/web/lists/getbytitle('" + listTitle + "')"

List Item EntityType FullName

Для взаимодействия с данными, хранящимися в списке или библиотеке документов мы должны знать полное имя сущности. Получить это имя можно из соответствующего списка с помощью GET-запроса:

var url = _spPageContextInfo.webServerRelativeUrl + "_api/web/lists/getbytitle('" + listTitle + "')?$select=ListItemEntityTypeFullName"

Ответ от сервера будет содержать нужное нам значение:

<?xml version="1.0" encoding="utf-8"?>
<entry>
    <id>https://{YOUR_TENANT_NAME}.sharepoint.com/_api/Web/Lists(guid'{YOUR_LIST_ID}')</id>
    <category term="SP.List" scheme="http://schemas.microsoft.com/ado/2007/08/dataservices/scheme" />
    <link rel="edit" href="Web/Lists(guid'{YOUR_LIST_ID}')" />
    <content type="application/xml">
        <m:properties>
            <d:ListItemEntityTypeFullName>SP.Data.CRUDListListItem</d:ListItemEntityTypeFullName>
        </m:properties>
    </content>
</entry>

В моём случае имя сущности - SP.Data.CRUDListListItem.

Итак, у нас есть всё необходимое, чтобы начать: дайджест из скрытого поля страницы, имя списка, которое нам известно, относительный url сайта из объекта _spPageContextInfo и значение свойстваListItemEntityTypeFullName нашего списка.

Начнем с простого и будем постепенно переходить к сложному. Во всех примерах я покажу как выполнять четыре операции: Создание, Чтение, Обновление и Удаление.

Текст

Самый простой пример использования REST API.

Создание

Чтобы добавить новый элемент списка мы должны выполнить POST-запрос:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- дайджест
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- имя сущности
        "Title": "TextFieldValue" // <-- "Имя поля": "Значение"
    })
});

Ответ от сервера в случае успешного завершения операции будет содержать свойства созданного элемента и статус запроса будет HTTP 201 Created:

<?xml version="1.0" encoding="utf-8"?>
<entry>
    <content type="application/xml">
        <m:properties>
            <d:Id m:type="Edm.Int32">3</d:Id>
            <d:Title>TextFieldValue</d:Title>
        </m:properties>
    </content>
</entry>

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

Чтение

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

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items(3)?$select=Title", // <-- Идентификатор элемента 
    type: "GET",
    headers: {
        "Content-Type": "application/json;odata=verbose"
    }
});

Обновление

Запрос на обновление должен содержать два дополнительных заголовка: X-HTTP-Method и IF-MATCH:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items(3)", // <-- lsit item id
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val(), // <-- дайджест
        "X-HTTP-Method": "MERGE", // <--  заголовки для запроса на обновление
        "IF-MATCH": "*" // <--  заголовки для запроса на обновление
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- имя сущности
        "Title": "NewFieldValue" // <-- "Имя поля": "Значение"
    })
});

Ответ на запрос обновления имеет статус 304 No Content (если всё прошло хорошо).

Значения всех полей необходимо передавать?

Нет, только те поля и значения, которые необходимо обновить. Поля не представленные в запросе обновлены не будут.

Удаление

Просто укажите значение поля равным null чтобы удалить его содержимое.

$.ajax({
    // другие параметры запроса
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- имя сущности
        "Title": null // <-- удаляем значение поля
    })
});

Выбор

Создание

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

Первый запрос на создание элемента с ожидаемым значением поля выбор:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- дайджест
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- имя сущности
        "SingleChoiceField": "Choice 1" // <-- "Имя поля": "Значение"
    })
});

И новый элемент в списке:

Обратите внимание на поведение SharePoint: SharePoint REST API позволяет создавать/обновлять элементы без заполнения обязательных полей!

Чтение

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

Обновление

Для запроса на обновление я пробую казать невалидные значения для значения поля:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items(3)", // <-- Идентификатор элемента
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val(), // <-- дайджест
        "X-HTTP-Method": "MERGE", // <-- for update request
        "IF-MATCH": "*" // <-- заголовки для запроса на обновление
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- имя сущности
        "SingleChoiceField": "NotValidValue" // <-- "Имя поля": "Значение"
    })
});

Как видно, за валидацией надо следить самому при использовании SharePoint REST API:

Удаление

Смотрите раздел удаление для текстовых полей.

Множественный выбор

Работа с текстовыми полями и полем выбора (единственного) идентична. Но в случае множественного выбора есть несколько важных моментов, о которых надо помнить.

Создание

Значение поля множественного выбора должно быть представлено объектом Collection(Edm.String):

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- дайджест
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- имя сущности
        "MultiChoiceField": {
                "__metadata": {"type": "Collection(Edm.String)"},
                "results": [ // <-- array of values
                        "Choice 1",
                        "Choice 2"
                ]
        }
    })
});

Чтение

GET-запрос

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items(3)?$select=MultiChoiceField", // <-- Идентификатор элемента
    type: "GET",
    headers: {
        "Content-Type": "application/json;odata=verbose"
    }
});

Ответ от сервера содержит массив значений:

<?xml version="1.0" encoding="utf-8"?>
<entry>
    <category term="SP.Data.CRUDListListItem" />
    <content type="application/xml">
        <m:properties>
            <d:MultiChoiceField m:type="Collection(Edm.String)">
                <d:element>Choice 1</d:element>
                <d:element>Choice 2</d:element>
            </d:MultiChoiceField>
        </m:properties>
    </content>
</entry>

Обновление

Ещё один правильный запрос с неправильными значениями в поле множественного выбора:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items(3)", // <-- Идентификатор элемента
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val(), // <-- дайджест
        "X-HTTP-Method": "MERGE", // <--  заголовки для запроса на обновление
        "IF-MATCH": "*" // <--  заголовки для запроса на обновление
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- имя сущности
        "MultiChoiceField": {
                "__metadata": {"type": "Collection(Edm.String)"},
                "results": [ // <-- массив значений
                        "NotValidValue 1",
                        "NotValidValue 2"
                ]
        }
    })
});

Удаление

Смотрите раздел удаление для текстовых полей.

Единственная подстановка/Пользователь

Поле выбора пользователя унаследовано от поля подстановки. Поэтому работа с обеими этими типами полей работа идентична в REST API.

Создание

В случае подстановки/пользователя достаточно передать только идентификатор элемента. Имя поля в запросе должно иметь вид Id. Просто добавьте "Id" к имени поля:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- дайджест
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- имя сущности
        "SingleLookupId": 1 // <-- Идентификатор элемента подстановки
    })
});

Чтение

Для чтения значения из поля подстановки можно использовать псевдо-поле Id для получения идентификатор элемента. Для получения полного набора идентификатора и текстового поля элемента необходимо указывать само поле в параметре $expand запроса:

var restUrl = "/_api/web/lists/getbytitle('CRUDList')/items(3)?"+
    "$select=SingleLookupId,SingleLookup/Id,SingleLookup/Title&"+ // <-- select id and projected fields
    "$expand=SingleLookup"; // <-- expand lookup field
$.ajax({
    url: restUrl,
    type: "GET"
});

Ответ на запрос от сервера:

<?xml version="1.0" encoding="utf-8"?>
<entry>
    <link title="SingleLookup">
        <m:inline>
            <entry>
                <content type="application/xml">
                    <m:properties>
                        <d:Id m:type="Edm.Int32">2</d:Id>
                        <d:Title>Item 2</d:Title>
                    </m:properties>
                </content>
            </entry>
        </m:inline>
    </link>
    <content type="application/xml">
        <m:properties>
            <d:SingleLookupId m:type="Edm.Int32">2</d:SingleLookupId>
        </m:properties>
    </content>
</entry>

Обновление

Запрос на обновление идентичен запросу на создание. Просто добавьте идентификатор обновляемого элемента и необходимые заголовки запроса.

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- дайджест
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- имя сущности
        "SingleLookupId": 1 // <-- Идентификатор элемента подстановки
    })
});

Удаление

Смотрите раздел удаление для текстовых полей.

Множественная подстановка/Пользователи

Поле множественного выбора в запросах создания и обновления должно быть представлено массивом идентификаторов.

Имя поля множественной подстановки также должно содержать постфикс Id.

Create

Массив идентификаторов элементов подстановки в качестве значения поля:

$.ajax({
    url: "/_api/web/lists/getbytitle('CRUDList')/items",
    type: "POST",
    headers: {
        "Content-Type": "application/json;odata=verbose",
        "X-RequestDigest": $("#__REQUESTDIGEST").val() // <-- дайджест
    },
    data: JSON.stringify({
        "__metadata": { "type": "SP.Data.CRUDListListItem" }, // <-- имя сущности
        "MultiLookupId": {
                "results": [1, 2, 3]  // <-- Идентификатор элемента подстановки
        }
    })
});

Чтение

var restUrl = "/_api/web/lists/getbytitle('CRUDList')/items(3)?"+
    "$select=MultiLookupId,MultiLookup/Id,MultiLookup/Title&"+ // <-- select id and projected fields
    "$expand=MultiLookup"; // <-- expand lookup field
$.ajax({
    url: restUrl,
    type: "GET"
});

Ответ от сервера содержит массив идентификаторов и коллекцию объектов с выбранными полями:

<?xml version="1.0" encoding="utf-8"?>
<entry>
    <link title="MultiLookup">
        <m:inline>
            <feed>
                <entry>
                    <content type="application/xml">
                        <m:properties>
                            <d:Id m:type="Edm.Int32">1</d:Id>
                            <d:Title>Item 1</d:Title>
                        </m:properties>
                    </content>
                </entry>
                <entry>
                    <content type="application/xml">
                        <m:properties>
                            <d:Id m:type="Edm.Int32">2</d:Id>
                            <d:Title>Item 2</d:Title>
                        </m:properties>
                    </content>
                </entry>
                <entry>
                    <content type="application/xml">
                        <m:properties>
                            <d:Id m:type="Edm.Int32">3</d:Id>
                            <d:Title>Item 3</d:Title>
                        </m:properties>
                    </content>
                </entry>
            </feed>
        </m:inline>
    </link>
    <content type="application/xml">
        <m:properties>
            <d:MultiLookupId m:type="Collection(Edm.Int32)">
                <d:element>1</d:element>
                <d:element>2</d:element>
                <d:element>3</d:element>
            </d:MultiLookupId>
        </m:properties>
    </content>
</entry>

Обновление

Запрос на обновление идентичен запросу на создание. Просто добавьте идентификатор обновляемого элемента и необходимые заголовки запроса.

Удаление

Смотрите раздел удаление для текстовых полей.

Работа с другими типами полей такими как метаданные, ссылка и другими я покажу во второй части этого поста.

Виталий Жуков

Виталий Жуков

SharePoint архитектор, разработчик, тренер, Microsoft MVP (Office Development). Более 15 лет опыта работы с SharePoint, Dynamics CRM, Office 365, и другими продуктами и сервисами Microsoft.

Смотрите также

EntityFramework. Оптимистические блокировки

EntityFramework. Оптимистические блокировки

Linq to Sharepoint. Особенности

Linq to Sharepoint. Особенности

SharePoint 2010. Настройка входящей почты для кастомного списка

SharePoint 2010. Настройка входящей почты для кастомного списка

SharePoint 2010. PeopleEditor. Установка значения

SharePoint 2010. PeopleEditor. Установка значения

Linq to SharePoint. Особенности. Часть 2

Linq to SharePoint. Особенности. Часть 2