Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
278fc5b
SP Initial
dynaway-kmi Jun 14, 2022
ee15cd6
file and variable naming
dynaway-kmi Jun 24, 2022
a720c9a
Request digest error handling
dynaway-kmi Jun 24, 2022
b2ac854
Naming, Spacing
dynaway-kmi Jul 5, 2022
2fbe416
added [NonDebuggable] when handling token
dynaway-kmi Jul 5, 2022
cca5983
variable naming
dynaway-kmi Jul 5, 2022
5463adf
Data Classification
dynaway-kmi Jul 5, 2022
7e11cd0
PermissionSet aded to System Application - Objects
dynaway-kmi Jul 6, 2022
9a3d43e
ListId on List Item
dynaway-kmi Jul 8, 2022
0b7c057
folder structure and empty lines
dynaway-kmi Jul 8, 2022
7e63d78
Authorization and access property
dynaway-kmi Jul 11, 2022
9a004bf
Enum comment
dynaway-kmi Jul 13, 2022
514534e
Tests
dynaway-kmi Jul 15, 2022
946ca48
request length
dynaway-kmi Jul 15, 2022
ea17965
User-Agent
dynaway-kmi Jul 15, 2022
fbd4f01
Error handling and request decoration
dynaway-kmi Jul 28, 2022
de0c7c8
Test library
dynaway-kmi Jul 29, 2022
458a16a
Authorization and tests
dynaway-kmi Aug 23, 2022
523f03c
fix
dynaway-kmi Aug 23, 2022
dfb70c9
Readme
dynaway-kmi Aug 23, 2022
2b15ecd
Readme
dynaway-kmi Aug 23, 2022
cbee7c3
DataClassification, AuthenticationCode ...
dynaway-kmi Sep 28, 2022
c486ef0
Add license headers to new code files
mazhelez Oct 4, 2022
59877ee
remove user credentials
dynaway-kmi Oct 4, 2022
c949012
remove user cred tests
dynaway-kmi Oct 4, 2022
366b9d1
Merge remote-tracking branch 'origin/kmi' into KMI
dynaway-kmi Oct 4, 2022
17f2143
Minor fixes
mazhelez Oct 5, 2022
bd0ac07
Merge branch 'main' of https://github.com/microsoft/ALAppExtensions i…
mazhelez Oct 6, 2022
16cdeb3
Update versions in app.json-s
mazhelez Oct 7, 2022
2062073
Hide "SharePoint Diagnostics" behind an interface + some minor improv…
mazhelez Oct 12, 2022
4ba44cf
Fix referenec to interface
mazhelez Oct 13, 2022
600a4de
Merge branch 'main' into KMI
mazhelez Nov 7, 2022
b0eadfa
Metadata
dynaway-kmi Mar 14, 2023
dcd0e94
Merge remote-tracking branch 'refs/remotes/origin/kmi' into kmi
dynaway-kmi Jun 9, 2023
1a6bd37
Fixing events
dynaway-kmi Jun 9, 2023
745c91c
Merge issue fix
dynaway-kmi Jun 9, 2023
428002a
Documentation
dynaway-kmi Jun 9, 2023
002198d
Merge branch 'main' into kmi
dynaway-kmi Jul 19, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Modules/System/SharePoint/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,16 @@ Downloads specified file to the client.
SPClient.DownloadFileContent(SharePointFile.OdataId, SharePointFile.Name);
```

### Update Metadata for a list item (including a file)
Updates specific metadata field for list item.
In order to update metadata of a file it needs to be accessed as list item.
```
var
SharePointFile: Record "SharePoint File";
begin
SharePointClient.UpdateListItemMetaDataField('Maintenance', 10, 'SP.Data.MaintenanceItem', 'WorkOrderNo', 'TEST0001');
```

## Error handling

### Retrieve diagnostic information
Expand Down
82 changes: 79 additions & 3 deletions Modules/System/SharePoint/src/SharePointClient.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ codeunit 9100 "SharePoint Client"
/// <summary>
/// Gets all list items for the given list.
/// </summary>
/// <raises>ProcessSharePointListItemMetadata</raises>
/// <param name="ListTitle">The title of the list/</param>
/// <param name="SharePointListItem">Collection of the result (temporary record).</param>
/// <returns>True if the operation was successful; otherwise - false.</returns>
Expand All @@ -69,6 +70,7 @@ codeunit 9100 "SharePoint Client"
/// <summary>
/// Gets all list items for the given list.
/// </summary>
/// <raises>ProcessSharePointListItemMetadata</raises>
/// <param name="ListId">The GUID of the list/</param>
/// <param name="SharePointListItem">Collection of the result (temporary record).</param>
/// <returns>True if the operation was successful; otherwise - false.</returns>
Expand Down Expand Up @@ -207,6 +209,7 @@ codeunit 9100 "SharePoint Client"
/// <summary>
/// Creates a new list item in specific list.
/// </summary>
/// <raises>ProcessSharePointListItemMetadata</raises>
/// <param name="ListTitle">The title of the list.</param>
/// <param name="ListItemEntityTypeFullName">The Entity Type for the list. Parameter can be found on a list object (ListItemEntityType).</param>
/// <param name="ListItemTitle">The title of the new list item.</param>
Expand All @@ -220,6 +223,7 @@ codeunit 9100 "SharePoint Client"
/// <summary>
/// Creates a new list item in specific list.
/// </summary>
/// <raises>ProcessSharePointListItemMetadata</raises>
/// <param name="ListId">The GUID of the list.</param>
/// <param name="ListItemEntityTypeFullName">The Entity Type for the list. Parameter can be found on a list object (ListItemEntityType).</param>
/// <param name="ListItemTitle">The title of the new list item.</param>
Expand Down Expand Up @@ -249,12 +253,26 @@ codeunit 9100 "SharePoint Client"
/// <summary>
/// Lists all files in the given folder.
/// </summary>
/// <raises>ProcessSharePointFileMetadata</raises>
/// <param name="ServerRelativeUrl">URL of the parent folder.</param>
/// <param name="SharePointFile">Collection of the result (temporary record).</param>
/// <returns>True if the operation was successful; otherwise - false.</returns>
procedure GetFolderFilesByServerRelativeUrl(ServerRelativeUrl: Text; var SharePointFile: Record "SharePoint File" temporary): Boolean
begin
exit(SharePointClientImpl.GetFolderFilesByServerRelativeUrl(ServerRelativeUrl, SharePointFile));
exit(SharePointClientImpl.GetFolderFilesByServerRelativeUrl(ServerRelativeUrl, SharePointFile, false));
end;

/// <summary>
/// Lists all files in the given folder.
/// </summary>
/// <raises>ProcessSharePointFileMetadata</raises>
/// <param name="ServerRelativeUrl">URL of the parent folder.</param>
/// <param name="SharePointFile">Collection of the result (temporary record).</param>
/// <param name="ListAllFields">Include metadata in results.</param>
/// <returns>True if the operation was successful; otherwise - false.</returns>
procedure GetFolderFilesByServerRelativeUrl(ServerRelativeUrl: Text; var SharePointFile: Record "SharePoint File" temporary; ListAllFields: Boolean): Boolean
begin
exit(SharePointClientImpl.GetFolderFilesByServerRelativeUrl(ServerRelativeUrl, SharePointFile, ListAllFields));
end;

/// <summary>
Expand Down Expand Up @@ -306,18 +324,34 @@ codeunit 9100 "SharePoint Client"
/// <summary>
/// Adds a file to specific folder.
/// </summary>
/// <raises>ProcessSharePointFileMetadata</raises>
/// <remarks>Requires UI interaction to pick a file.</remarks>
/// <param name="ServerRelativeUrl">URL of the parent folder.</param>
/// <param name="SharePointFile">Collection of the result (temporary record). Always one element.</param>
/// <returns>True if the operation was successful; otherwise - false.</returns>
procedure AddFileToFolder(ServerRelativeUrl: Text; var SharePointFile: Record "SharePoint File" temporary): Boolean
begin
exit(SharePointClientImpl.AddFileToFolder(ServerRelativeUrl, SharePointFile));
exit(SharePointClientImpl.AddFileToFolder(ServerRelativeUrl, SharePointFile, false));
end;

/// <summary>
/// Adds a file to specific folder.
/// </summary>
/// <raises>ProcessSharePointFileMetadata</raises>
/// <remarks>Requires UI interaction to pick a file.</remarks>
/// <param name="ServerRelativeUrl">URL of the parent folder.</param>
/// <param name="SharePointFile">Collection of the result (temporary record). Always one element.</param>
/// <param name="ListAllFields">Include metadata in results.</param>
/// <returns>True if the operation was successful; otherwise - false.</returns>
procedure AddFileToFolder(ServerRelativeUrl: Text; var SharePointFile: Record "SharePoint File" temporary; ListAllFields: Boolean): Boolean
begin
exit(SharePointClientImpl.AddFileToFolder(ServerRelativeUrl, SharePointFile, ListAllFields));
end;

/// <summary>
/// Adds a file to specific folder.
/// </summary>
/// <raises>ProcessSharePointFileMetadata</raises>
/// <remarks>Does not require UI interaction.</remarks>
/// <param name="ServerRelativeUrl">URL of the parent folder.</param>
/// <param name="FileName">File name to use on SharePoint.</param>
Expand All @@ -326,7 +360,49 @@ codeunit 9100 "SharePoint Client"
/// <returns>True if the operation was successful; otherwise - false.</returns>
procedure AddFileToFolder(ServerRelativeUrl: Text; FileName: Text; var FileInStream: InStream; var SharePointFile: Record "SharePoint File" temporary): Boolean
begin
exit(SharePointClientImpl.AddFileToFolder(ServerRelativeUrl, FileName, FileInStream, SharePointFile));
exit(SharePointClientImpl.AddFileToFolder(ServerRelativeUrl, FileName, FileInStream, SharePointFile, false));
end;

/// <summary>
/// Adds a file to specific folder.
/// </summary>
/// <raises>ProcessSharePointFileMetadata</raises>
/// <remarks>Does not require UI interaction.</remarks>
/// <param name="ServerRelativeUrl">URL of the parent folder.</param>
/// <param name="FileName">File name to use on SharePoint.</param>
/// <param name="FileInStream">File stream to upload.</param>
/// <param name="SharePointFile">Collection of the result (temporary record). Always one element.</param>
/// <param name="ListAllFields">Include metadata in results.</param>
/// <returns>True if the operation was successful; otherwise - false.</returns>
procedure AddFileToFolder(ServerRelativeUrl: Text; FileName: Text; var FileInStream: InStream; var SharePointFile: Record "SharePoint File" temporary; ListAllFields: Boolean): Boolean
begin
exit(SharePointClientImpl.AddFileToFolder(ServerRelativeUrl, FileName, FileInStream, SharePointFile, ListAllFields));
end;

/// <summary>
/// Updates metadata field for list item.
/// </summary>
/// <param name="ListTitle">The title of the list.</param>
/// <param name="ListItemEntityTypeFullName">The Entity Type for the list. Parameter can be found on a list object (ListItemEntityType).</param>
/// <param name="FieldName">The name of the metadata field.</param>
/// <param name="FieldValue">Value.</param>
/// <returns>True if the operation was successful; otherwise - false.</returns>
procedure UpdateListItemMetaDataField(ListTitle: Text; ItemId: Integer; ListItemEntityTypeFullName: Text; FieldName: Text; FieldValue: Text): Boolean
begin
exit(SharePointClientImpl.UpdateListItemMetaDataField(ListTitle, ItemId, ListItemEntityTypeFullName, FieldName, FieldValue));
end;

/// <summary>
/// Updates metadata field for list item.
/// </summary>
/// <param name="ListTitle">The GUID of the list.</param>
/// <param name="ListItemEntityTypeFullName">The Entity Type for the list. Parameter can be found on a list object (ListItemEntityType).</param>
/// <param name="FieldName">The name of the metadata field.</param>
/// <param name="FieldValue">Value.</param>
/// <returns>True if the operation was successful; otherwise - false.</returns>
procedure UpdateListItemMetaDataField(ListId: Guid; ItemId: Integer; ListItemEntityTypeFullName: Text; FieldName: Text; FieldValue: Text): Boolean
begin
exit(SharePointClientImpl.UpdateListItemMetaDataField(ListId, ItemId, ListItemEntityTypeFullName, FieldName, FieldValue));
end;

#endregion
Expand Down
76 changes: 73 additions & 3 deletions Modules/System/SharePoint/src/SharePointClientImpl.Codeunit.al
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ codeunit 9101 "SharePoint Client Impl."
SharePointUriBuilder.SetMethod('Lists', ListId);
SharePointUriBuilder.SetObject('items');


SharePointRequestHelper.SetAuthorization(Authorization);
SharePointOperationResponse := SharePointRequestHelper.Get(SharePointUriBuilder);
if not SharePointOperationResponse.GetDiagnostics().IsSuccessStatusCode() then
Expand Down Expand Up @@ -458,14 +459,16 @@ codeunit 9101 "SharePoint Client Impl."
exit(true);
end;

procedure GetFolderFilesByServerRelativeUrl(ServerRelativeUrl: Text; var SharePointFile: Record "SharePoint File" temporary): Boolean
procedure GetFolderFilesByServerRelativeUrl(ServerRelativeUrl: Text; var SharePointFile: Record "SharePoint File" temporary; ListAllFields: Boolean): Boolean
var
SharePointFileParser: Codeunit "SharePoint File";
Result: Text;
begin
SharePointUriBuilder.ResetPath();
SharePointUriBuilder.SetMethod('GetFolderByServerRelativeUrl', ServerRelativeUrl);
SharePointUriBuilder.SetObject('Files');
if ListAllFields then
SharePointUriBuilder.AddQueryParameter('$expand', 'ListItemAllFields');

SharePointRequestHelper.SetAuthorization(Authorization);
SharePointOperationResponse := SharePointRequestHelper.Get(SharePointUriBuilder);
Expand Down Expand Up @@ -626,6 +629,7 @@ codeunit 9101 "SharePoint Client Impl."
exit(true);
end;


procedure DeleteFolder(OdataId: Text): Boolean
begin
//DELETE https://{site_url}/_api/web/GetFolderByServerRelativeUrl('{folder_name}')
Expand Down Expand Up @@ -653,7 +657,7 @@ codeunit 9101 "SharePoint Client Impl."
exit(true);
end;

procedure AddFileToFolder(ServerRelativeUrl: Text; var SharePointFile: Record "SharePoint File" temporary): Boolean
procedure AddFileToFolder(ServerRelativeUrl: Text; var SharePointFile: Record "SharePoint File" temporary; ListAllFields: Boolean): Boolean
var
SharePointFileParser: Codeunit "SharePoint File";
SharePointHttpContent: Codeunit "SharePoint Http Content";
Expand All @@ -669,6 +673,8 @@ codeunit 9101 "SharePoint Client Impl."
SharePointUriBuilder.SetMethod('GetFolderByServerRelativeUrl', ServerRelativeUrl);
SharePointUriBuilder.SetObject('Files');
SharePointUriBuilder.SetMethod('add', 'url', '''' + FileName + '''');
if ListAllFields then
SharePointUriBuilder.AddQueryParameter('$expand', 'ListItemAllFields');

SharePointHttpContent.FromFileInStream(FileInStream);
SharePointRequestHelper.SetAuthorization(Authorization);
Expand All @@ -681,7 +687,7 @@ codeunit 9101 "SharePoint Client Impl."
exit(true);
end;

procedure AddFileToFolder(ServerRelativeUrl: Text; FileName: Text; var FileInStream: InStream; var SharePointFile: Record "SharePoint File" temporary): Boolean
procedure AddFileToFolder(ServerRelativeUrl: Text; FileName: Text; var FileInStream: InStream; var SharePointFile: Record "SharePoint File" temporary; ListAllFields: Boolean): Boolean
var
SharePointFileParser: Codeunit "SharePoint File";
SharePointHttpContent: Codeunit "SharePoint Http Content";
Expand All @@ -692,6 +698,8 @@ codeunit 9101 "SharePoint Client Impl."
SharePointUriBuilder.SetMethod('GetFolderByServerRelativeUrl', ServerRelativeUrl);
SharePointUriBuilder.SetObject('Files');
SharePointUriBuilder.SetMethod('add', 'url', '''' + FileName + '''');
if ListAllFields then
SharePointUriBuilder.AddQueryParameter('$expand', 'ListItemAllFields');

SharePointHttpContent.FromFileInStream(FileInStream);
SharePointRequestHelper.SetAuthorization(Authorization);
Expand All @@ -703,5 +711,67 @@ codeunit 9101 "SharePoint Client Impl."
SharePointFileParser.ParseSingleReturnValue(Result, SharePointFile);
exit(true);
end;

procedure UpdateListItemMetaDataField(ListTitle: Text; ItemId: Integer; ListItemEntityTypeFullName: Text; FieldName: Text; FieldValue: Text): Boolean
var
SharePointHttpContent: Codeunit "SharePoint Http Content";
Metadata, Payload : JsonObject;
Txt: Text;
begin
SharePointUriBuilder.ResetPath();
SharePointUriBuilder.SetObject('lists');
SharePointUriBuilder.SetMethod('GetByTitle', ListTitle);
SharePointUriBuilder.SetMethod('items', ItemId);

Metadata.Add('type', ListItemEntityTypeFullName);
Payload.Add('__metadata', Metadata);
Payload.Add(FieldName, FieldValue);

SharePointHttpContent.FromJson(Payload);

SharePointHttpContent.GetContent().ReadAs(Txt);

SharePointHttpContent.SetRequestDigest(GetRequestDigest(SharePointUriBuilder.GetHost()));
SharePointHttpContent.SetXHttpMethod('MERGE');
SharePointHttpContent.SetIfMatch('*');

SharePointOperationResponse := SharePointRequestHelper.Patch(SharePointUriBuilder, SharePointHttpContent);
if not SharePointOperationResponse.GetDiagnostics().IsSuccessStatusCode() then
exit(false);

SharePointOperationResponse.GetResultAsText(Txt);
Message(Txt);
exit(true);
end;

procedure UpdateListItemMetaDataField(ListId: Guid; ItemId: Integer; ListItemEntityTypeFullName: Text; FieldName: Text; FieldValue: Text): Boolean
var
SharePointHttpContent: Codeunit "SharePoint Http Content";
Metadata, Payload : JsonObject;
Txt: Text;
begin
SharePointUriBuilder.ResetPath();
SharePointUriBuilder.SetMethod('Lists', ListId);
SharePointUriBuilder.SetMethod('items', ItemId);

Metadata.Add('type', ListItemEntityTypeFullName);
Payload.Add('__metadata', Metadata);
Payload.Add(FieldName, FieldValue);

SharePointHttpContent.FromJson(Payload);

SharePointHttpContent.GetContent().ReadAs(Txt);

SharePointHttpContent.SetRequestDigest(GetRequestDigest(SharePointUriBuilder.GetHost()));
SharePointHttpContent.SetXHttpMethod('MERGE');
SharePointHttpContent.SetIfMatch('*');

SharePointOperationResponse := SharePointRequestHelper.Patch(SharePointUriBuilder, SharePointHttpContent);
if not SharePointOperationResponse.GetDiagnostics().IsSuccessStatusCode() then
exit(false);

SharePointOperationResponse.GetResultAsText(Txt);
exit(true);
end;
#endregion
}
26 changes: 26 additions & 0 deletions Modules/System/SharePoint/src/SharePointEvents.Codeunit.al
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
codeunit 9112 "SharePoint Events"
{
Access = Public;

[IntegrationEvent(false, false)]
/// <summary>
/// Process SharePointFile Metadata - Use to extract custom meta data into model record
/// </summary>
/// <remarks>Extend the "SharePoint File" table to store any custom data.</remarks>
/// <param name="Metadata">__metadata node of SharePointFile Json Object</param>
/// <param name="SharePointFile">SharePointFile temporary record.</param>
internal procedure ProcessSharePointFileMetadata(Metadata: JsonToken; var SharePointFile: Record "SharePoint File" temporary)
begin
end;

[IntegrationEvent(false, false)]
/// <summary>
/// Process SharePointListItem Metadata - Use to extract custom mete data into model record
/// </summary>
/// <remarks>Extend the "SharePoint List Item" table to store any custom data.</remarks>
/// <param name="Metadata">__metadata node of SharePointListItem Json Object</param>
/// <param name="SharePointListItem">SharePointListItem temporary record.</param>
internal procedure ProcessSharePointListItemMetadata(Metadata: JsonToken; var SharePointListItem: Record "SharePoint List Item" temporary)
begin
end;
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ codeunit 9107 "SharePoint Http Content"
ContentLength: Integer;
ContentType: Text;
RequestDigest: Text;
XHttpMethod: Text;
IfMatch: Text;

procedure FromFileInStream(var FileInStream: Instream)
begin
Expand Down Expand Up @@ -57,6 +59,26 @@ codeunit 9107 "SharePoint Http Content"
exit(RequestDigest);
end;

procedure SetXHttpMethod(XHttpMethodValue: Text)
begin
XHttpMethodValue := XHttpMethodValue;
end;

procedure GetXHttpMethod(): Text;
begin
exit(XHttpMethod);
end;

procedure SetIfMatch(IfMatchValue: Text)
begin
IfMatch := IfMatchValue;
end;

procedure GetIfMatch(): Text;
begin
exit(IfMatch);
end;

local procedure GetContentLength(var SourceInStream: InStream) Length: Integer
var
MemoryStream: DotNet MemoryStream;
Expand Down
Loading