Sobre nós Guias Projetos Contactos
Админка
please wait

O SharePoint é a plataforma de colaboração empresarial da Microsoft, amplamente utilizada para gestão documental, intranets e sites de equipa. A integração com o SharePoint — seja para adicionar funcionalidades personalizadas, automatizar fluxos de trabalho ou criar extensões — exige compreender a sua arquitetura e APIs. Este guia aborda padrões essenciais de integração com o SharePoint na perspetiva de um programador sénior.

Porquê a Integração com o SharePoint

A integração com o SharePoint permite:

  1. Funcionalidades Personalizadas: Ir além das capacidades incorporadas
  2. Automatização de Fluxos de Trabalho: Simplificar processos de negócio
  3. Migração de Dados: Mover conteúdo de/para o SharePoint
  4. Ligações Externas: Integrar aplicações line-of-business
  5. UX Melhorada: Melhorar a experiência do utilizador com UI personalizada

Visão Geral da Arquitetura do SharePoint

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

Integração com REST API

Autenticação

// 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;
}
}

Operações Básicas

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);
}
}

Adicionar Upload de Imagens Personalizado ao Wiki

A caixa de diálogo de imagens predefinida do SharePoint Wiki apenas suporta inserção por URL. Eis como adicionar a capacidade de upload de ficheiros:

O Desafio

O editor Wiki incorporado do SharePoint Services 3.0 não tem funcionalidade de upload de imagens — só é possível inserir imagens via URL. Isto obriga os utilizadores a: 1. Fazer upload das imagens separadamente para uma biblioteca de documentos 2. Copiar o URL da imagem 3. Colar o URL no editor do Wiki

Solução: Caixa de Diálogo de Upload Personalizada

Modificar a caixa de diálogo do Rich Text Editor para incluir upload de ficheiros:

<%-- 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>

Integração com o Rich Text Editor

Modificar RteDialog.aspx na pasta layouts para adicionar um separador de upload:

// Adicionar à secção de script de 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) {
// Inserir imagem com o URL devolvido
insertImage(returnValue);
}
}
};
SP.UI.ModalDialog.showModalDialog(options);
}
function insertImage(imageUrl) {
var imgHtml = '<img src="' + imageUrl + '" alt="Uploaded image" />';
// Obter a instância do RTE e inserir
var editor = RTE.RichTextEditor.getEditor(document.getElementById('txtContent'));
editor.pasteHtml(imgHtml);
}

Configuração

Adicionar ao web.config:

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

Web Parts do SharePoint Framework (SPFx)

O SharePoint moderno utiliza SPFx para desenvolvimento personalizado:

// 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');
}
}

Integração com Power Automate (Flow)

Criar fluxos de trabalho automatizados:

{
"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']}"
}
}
}
}
}
}

Automatização com PnP PowerShell

# Ligar ao SharePoint Online
Connect-PnPOnline -Url "https://contoso.sharepoint.com/sites/mysite" -Interactive
# Obter todos os documentos
$items = Get-PnPListItem -List "Documents"
foreach ($item in $items) {
Write-Host $item["FileLeafRef"]
}
# Fazer upload do ficheiro
Add-PnPFile -Path "C:\local\document.pdf" -Folder "Shared Documents"
# Criar item de lista
Add-PnPListItem -List "Tasks" -Values @{
"Title" = "New Task"
"DueDate" = (Get-Date).AddDays(7)
"AssignedTo" = "[email protected]"
}
# Atualizar permissões
Set-PnPListItemPermission -List "Documents" -Identity 1 -User "[email protected]" -AddRole "Contribute"

Principais Conclusões

  1. Escolher a API certa: REST para simplicidade, CSOM para operações complexas
  2. Tratar a autenticação corretamente: Azure AD para SharePoint Online
  3. Usar SPFx para UI moderna: Web parts e extensões
  4. Tirar partido do Power Automate: Automatização de fluxos de trabalho sem código
  5. Testar num tenant de desenvolvimento: Nunca testar em produção
  6. Seguir a governação: Respeitar permissões e políticas do site

A integração com o SharePoint vai desde chamadas REST simples até soluções personalizadas complexas — comece de forma simples e adicione complexidade apenas quando necessário.

 
 
 
Языки
Темы
Copyright © 1999 — 2026
ZK Interactive