SharePoint List REST API. Часть 1
Основные операции по работе со списками и библиотеками документов описаны в статье Работа со списками и элементами списков с использованием REST. В этом посте я покажу как выполнять операции с большинством из существующих типов полей, таких как метаданные (Таксономия), множественный выбор, подстановка и другими.
Поля списка
Мой демонстрационный список содержит следующие поля:
Обязательным является только поле Title.
Перед тем как мы начнем работать с SharePoint REST API пара моментов о среде:
- Для выполнения запросов я использую jQuery
- JavaScript код доступен git репозитории github.com/vzhukov/sp-rest-listitem-crud
Простой 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>
Обновление
Запрос на обновление идентичен запросу на создание. Просто добавьте идентификатор обновляемого элемента и необходимые заголовки запроса.
Удаление
Смотрите раздел удаление для текстовых полей.
Работа с другими типами полей такими как метаданные, ссылка и другими я покажу во второй части этого поста.