О нас Руководства Проекты Контакты
Админка
пожалуйста подождите

SharePoint — корпоративная платформа для совместной работы от Microsoft, широко используемая для управления документами, интранетов и командных сайтов. Интеграция с SharePoint — будь то добавление пользовательской функциональности, автоматизация рабочих процессов или разработка расширений — требует понимания его архитектуры и API. В этом руководстве рассматриваются ключевые паттерны интеграции с SharePoint с точки зрения старшего разработчика.

Зачем нужна интеграция с SharePoint

Интеграция с SharePoint позволяет:

  1. Пользовательские функции: расширять возможности за пределами встроенного функционала
  2. Автоматизация рабочих процессов: оптимизировать бизнес-процессы
  3. Миграция данных: переносить контент в/из SharePoint
  4. Внешние подключения: интегрировать line-of-business-приложения
  5. Улучшенный UX: повышать удобство для пользователей с помощью пользовательского UI

Обзор архитектуры SharePoint

┌─────────────────────────────────────────────────────────┐
│ SharePoint Site │
├─────────────────────────────────────────────────────────┤
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Document │ │ List │ │ Wiki │ │
│ │ Library │ │ │ │ Pages │ │
│ └──────────┘ └──────────┘ └──────────┘ │
├─────────────────────────────────────────────────────────┤
│ Web Parts / Apps │
├─────────────────────────────────────────────────────────┤
│ REST API / CSOM / JSOM │
└─────────────────────────────────────────────────────────┘

Интеграция через REST API

Аутентификация

// SharePoint Online with Azure AD
using Microsoft.Identity.Client;
public class SharePointClient
{
private readonly string _siteUrl;
private readonly IConfidentialClientApplication _app;
public SharePointClient(string siteUrl, string clientId, string clientSecret, string tenantId)
{
_siteUrl = siteUrl;
_app = ConfidentialClientApplicationBuilder
.Create(clientId)
.WithClientSecret(clientSecret)
.WithAuthority($"https://login.microsoftonline.com/{tenantId}")
.Build();
}
public async Task<string> GetAccessTokenAsync()
{
var scopes = new[] { $"{_siteUrl}/.default" };
var result = await _app.AcquireTokenForClient(scopes).ExecuteAsync();
return result.AccessToken;
}
}

Базовые операции

public class SharePointService
{
private readonly HttpClient _client;
private readonly string _siteUrl;
public async Task<List<DocumentInfo>> GetDocumentsAsync(string libraryName)
{
var endpoint = $"{_siteUrl}/_api/web/lists/getbytitle('{libraryName}')/items";
var request = new HttpRequestMessage(HttpMethod.Get, endpoint);
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await _client.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
var data = JsonSerializer.Deserialize<SharePointResponse>(content);
return data.Value.Select(item => new DocumentInfo
{
Id = item.Id,
Title = item.Title,
FileRef = item.FileRef
}).ToList();
}
public async Task UploadFileAsync(string libraryName, string fileName, byte[] content)
{
var endpoint = $"{_siteUrl}/_api/web/lists/getbytitle('{libraryName}')" +
$"/RootFolder/Files/add(url='{fileName}',overwrite=true)";
var request = new HttpRequestMessage(HttpMethod.Post, endpoint);
request.Content = new ByteArrayContent(content);
await _client.SendAsync(request);
}
public async Task UpdateListItemAsync(string listName, int itemId, Dictionary<string, object> fields)
{
var endpoint = $"{_siteUrl}/_api/web/lists/getbytitle('{listName}')/items({itemId})";
var metadata = new { __metadata = new { type = $"SP.Data.{listName}ListItem" } };
var payload = fields.Concat(new[] { new KeyValuePair<string, object>("__metadata", metadata.__metadata) })
.ToDictionary(x => x.Key, x => x.Value);
var request = new HttpRequestMessage(HttpMethod.Post, endpoint);
request.Headers.Add("X-HTTP-Method", "MERGE");
request.Headers.Add("IF-MATCH", "*");
request.Content = new StringContent(
JsonSerializer.Serialize(payload),
Encoding.UTF8,
"application/json"
);
await _client.SendAsync(request);
}
}

Добавление пользовательской загрузки изображений в Wiki

Стандартное диалоговое окно изображений в SharePoint Wiki поддерживает только вставку по URL. Ниже описано, как добавить возможность загрузки файлов:

Проблема

Во встроенном Wiki-редакторе SharePoint Services 3.0 отсутствует функциональность загрузки изображений — можно вставлять изображения только по URL. Из-за этого пользователям приходится: 1. Отдельно загружать изображения в библиотеку документов 2. Копировать URL изображения 3. Вставлять URL в редактор Wiki

Решение: пользовательский диалог загрузки

Измените диалог Rich Text Editor, добавив загрузку файла:

<%-- UploadImage.aspx - Custom upload handler --%>
<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Page Language="C#" MasterPageFile="~/_layouts/simple.master" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="Microsoft.SharePoint.WebControls" %>
<script runat="server">
protected void UploadButton_Click(object sender, EventArgs e)
{
if (FileUpload1.HasFile)
{
try
{
// Get target library from web.config
string libraryUrl = ConfigurationManager.AppSettings["WikiImageLibrary"];
SPWeb web = SPContext.Current.Web;
SPFolder folder = web.GetFolder(libraryUrl);
string fileName = FileUpload1.FileName;
byte[] fileContent = FileUpload1.FileBytes;
// Upload file
SPFile file = folder.Files.Add(fileName, fileContent, true);
// Return URL to parent dialog
string imageUrl = web.Url + "/" + file.Url;
ClientScript.RegisterStartupScript(
this.GetType(),
"CloseDialog",
$"window.returnValue = '{imageUrl}'; window.close();",
true
);
}
catch (Exception ex)
{
ErrorLabel.Text = "Upload failed: " + ex.Message;
}
}
}
</script>
<asp:Content ContentPlaceHolderID="PlaceHolderMain" runat="server">
<h2>Upload Image to Wiki</h2>
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="UploadButton" runat="server"
Text="Upload"
OnClick="UploadButton_Click" />
<asp:Label ID="ErrorLabel" runat="server" ForeColor="Red" />
<div style="margin-top: 20px;">
<asp:Image ID="PreviewImage" runat="server" Visible="false" />
</div>
</asp:Content>

Интеграция с Rich Text Editor

Измените RteDialog.aspx в папке layouts, чтобы добавить вкладку загрузки:

// Добавить в секцию script файла RteDialog.aspx
function openImageUpload() {
var uploadUrl = '/_layouts/UploadImage.aspx';
var options = {
url: uploadUrl,
width: 500,
height: 300,
dialogReturnValueCallback: function(dialogResult, returnValue) {
if (dialogResult == SP.UI.DialogResult.OK && returnValue) {
// Вставить изображение, используя возвращённый URL
insertImage(returnValue);
}
}
};
SP.UI.ModalDialog.showModalDialog(options);
}
function insertImage(imageUrl) {
var imgHtml = '<img src="' + imageUrl + '" alt="Uploaded image" />';
// Получить экземпляр RTE и выполнить вставку
var editor = RTE.RichTextEditor.getEditor(document.getElementById('txtContent'));
editor.pasteHtml(imgHtml);
}

Конфигурация

Добавьте в web.config:

<configuration>
<appSettings>
<add key="WikiImageLibrary" value="WikiImages" />
</appSettings>
</configuration>

Веб-части SharePoint Framework (SPFx)

Современный SharePoint использует SPFx для пользовательской разработки:

// src/webparts/customList/CustomListWebPart.ts
import { Version } from '@microsoft/sp-core-library';
import { BaseClientSideWebPart } from '@microsoft/sp-webpart-base';
import { SPHttpClient, SPHttpClientResponse } from '@microsoft/sp-http';
export interface ICustomListWebPartProps {
listName: string;
}
export default class CustomListWebPart extends BaseClientSideWebPart<ICustomListWebPartProps> {
public render(): void {
this.domElement.innerHTML = `<div id="listItems">Loading...</div>`;
this.loadListItems();
}
private async loadListItems(): Promise<void> {
const endpoint = `${this.context.pageContext.web.absoluteUrl}` +
`/_api/web/lists/getbytitle('${this.properties.listName}')/items`;
try {
const response: SPHttpClientResponse = await this.context.spHttpClient.get(
endpoint,
SPHttpClient.configurations.v1
);
const data = await response.json();
this.renderItems(data.value);
} catch (error) {
this.domElement.innerHTML = `<div>Error loading items: ${error.message}</div>`;
}
}
private renderItems(items: any[]): void {
let html = '<ul>';
items.forEach(item => {
html += `<li>${item.Title}</li>`;
});
html += '</ul>';
this.domElement.querySelector('#listItems')!.innerHTML = html;
}
protected get dataVersion(): Version {
return Version.parse('1.0');
}
}

Интеграция с Power Automate (Flow)

Создавайте автоматизированные рабочие процессы:

{
"definition": {
"triggers": {
"When_a_file_is_created": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['sharepointonline']['connectionId']"
}
},
"method": "get",
"path": "/datasets/@{encodeURIComponent(encodeURIComponent('https://contoso.sharepoint.com/sites/mysite'))}/triggers/onnewfile",
"queries": {
"folderId": "Shared Documents"
}
}
}
},
"actions": {
"Send_email": {
"type": "ApiConnection",
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['office365']['connectionId']"
}
},
"method": "post",
"path": "/v2/Mail",
"body": {
"To": "[email protected]",
"Subject": "New file uploaded",
"Body": "A new file was uploaded: @{triggerOutputs()['headers']['x-ms-file-name']}"
}
}
}
}
}
}

Автоматизация с PnP PowerShell

# Подключиться к SharePoint Online
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/mysite" -Interactive
# Получить все документы
$items = Get-PnPListItem -List "Documents"
foreach ($item in $items) {
Write-Host $item["FileLeafRef"]
}
# Загрузить файл
Add-PnPFile -Path "C:\local\document.pdf" -Folder "Shared Documents"
# Создать элемент списка
Add-PnPListItem -List "Tasks" -Values @{
"Title" = "New Task"
"DueDate" = (Get-Date).AddDays(7)
"AssignedTo" = "[email protected]"
}
# Обновить разрешения
Set-PnPListItemPermission -List "Documents" -Identity 1 -User "[email protected]" -AddRole "Contribute"

Ключевые выводы

  1. Выберите правильный API: REST — для простоты, CSOM — для сложных операций
  2. Корректно обрабатывайте аутентификацию: Azure AD для SharePoint Online
  3. Используйте SPFx для современного UI: веб-части и расширения
  4. Используйте Power Automate: no-code-автоматизация рабочих процессов
  5. Тестируйте в development tenant: никогда не тестируйте в production
  6. Следуйте governance: соблюдайте разрешения сайта и политики

Интеграция с SharePoint варьируется от простых REST-запросов до сложных пользовательских решений — начинайте с простого и добавляйте сложность только по мере необходимости.

 
 
 
Языки
Темы
Copyright © 1999 — 2026
Зетка Интерактив