├── .gitignore ├── media ├── drives.png ├── drive-items.png ├── msnJournals.png └── sharepoint-connect.gif ├── src ├── OnlineCreateDriveFolder.Page.al ├── OnlineDrive.Table.al ├── OnlineDriveItem.Table.al ├── OnlineDrives.Page.al ├── OnlineDriveItems.Page.al └── OnlineDriveAPI.Codeunit.al ├── LICENSE ├── README.md └── app.json /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode 2 | .alpackages 3 | *.app -------------------------------------------------------------------------------- /media/drives.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msnraju/sp-document-explorer/HEAD/media/drives.png -------------------------------------------------------------------------------- /media/drive-items.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msnraju/sp-document-explorer/HEAD/media/drive-items.png -------------------------------------------------------------------------------- /media/msnJournals.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msnraju/sp-document-explorer/HEAD/media/msnJournals.png -------------------------------------------------------------------------------- /media/sharepoint-connect.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/msnraju/sp-document-explorer/HEAD/media/sharepoint-connect.gif -------------------------------------------------------------------------------- /src/OnlineCreateDriveFolder.Page.al: -------------------------------------------------------------------------------- 1 | page 50117 "Online Create Drive Folder" 2 | { 3 | PageType = StandardDialog; 4 | ApplicationArea = All; 5 | UsageCategory = Administration; 6 | 7 | layout 8 | { 9 | area(Content) 10 | { 11 | group(General) 12 | { 13 | ShowCaption = false; 14 | InstructionalText = 'Enter the folder name'; 15 | 16 | field(Name; FolderName) 17 | { 18 | ApplicationArea = All; 19 | } 20 | } 21 | } 22 | } 23 | 24 | var 25 | FolderName: Text; 26 | 27 | procedure GetFolderName(): Text 28 | begin 29 | exit(FolderName); 30 | end; 31 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 MSN Raju 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/OnlineDrive.Table.al: -------------------------------------------------------------------------------- 1 | table 50115 "Online Drive" 2 | { 3 | DataClassification = CustomerContent; 4 | 5 | fields 6 | { 7 | field(1; id; Text[250]) 8 | { 9 | DataClassification = CustomerContent; 10 | } 11 | field(2; name; Text[250]) 12 | { 13 | DataClassification = CustomerContent; 14 | } 15 | field(3; description; Text[250]) 16 | { 17 | DataClassification = CustomerContent; 18 | } 19 | field(4; driveType; Text[80]) 20 | { 21 | DataClassification = CustomerContent; 22 | } 23 | field(5; createdDateTime; DateTime) 24 | { 25 | DataClassification = CustomerContent; 26 | } 27 | field(6; lastModifiedDateTime; DateTime) 28 | { 29 | DataClassification = CustomerContent; 30 | } 31 | field(7; webUrl; Text[250]) 32 | { 33 | DataClassification = CustomerContent; 34 | } 35 | } 36 | 37 | keys 38 | { 39 | key(PK; id) 40 | { 41 | Clustered = true; 42 | } 43 | } 44 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Handling SharePoint Documents in Business Central 2 | 3 | This repository contains a sample project that integrates Business Central with SharePoint. 4 | 5 | This project is using "[Generic OAuth 2.0 Library](https://github.com/msnraju/BC-OAuth-2.0-Authorization)" as a dependency for [Microsoft Graph API](https://docs.microsoft.com/en-us/graph/use-the-api) Authentication Token. 6 | 7 | ## "Online Drives" ( page 50115 ) 8 | This page connects with the SharePoint root site and shows list of document libraries available in the root site. 9 | 10 | ![drives](/media/drives.png) 11 | 12 | You can also navigate through folders and files by clicking on the drive name. 13 | 14 | ## "Online Drive Items" ( page 50116 ) 15 | This page connects with the SharePoint document library and displays list of folders and files in that library. 16 | 17 | ![drives](/media/drive-items.png) 18 | 19 | You can perform the following operations: 20 | * Create a new folder 21 | * Upload a file 22 | * Download a file (click on the file name) 23 | * Delete a folder / file 24 | 25 | ## Code in Action 26 | 27 | ![SharePoint Connect](/media/sharepoint-connect.gif) 28 | 29 | For more information go to [msnJournals.com](https://www.msnjournals.com/post/how-to-connect-sharepoint-with-business-central) 30 | 31 | -------------------------------------------------------------------------------- /src/OnlineDriveItem.Table.al: -------------------------------------------------------------------------------- 1 | table 50116 "Online Drive Item" 2 | { 3 | DataClassification = CustomerContent; 4 | 5 | fields 6 | { 7 | field(1; id; Text[250]) 8 | { 9 | DataClassification = CustomerContent; 10 | } 11 | field(2; driveId; Text[250]) 12 | { 13 | DataClassification = CustomerContent; 14 | } 15 | field(3; parentId; Text[250]) 16 | { 17 | DataClassification = CustomerContent; 18 | } 19 | field(4; name; Text[250]) 20 | { 21 | DataClassification = CustomerContent; 22 | } 23 | field(5; isFile; Boolean) 24 | { 25 | DataClassification = CustomerContent; 26 | } 27 | field(6; mimeType; Text[80]) 28 | { 29 | DataClassification = CustomerContent; 30 | } 31 | field(7; size; BigInteger) 32 | { 33 | DataClassification = CustomerContent; 34 | } 35 | field(8; createdDateTime; DateTime) 36 | { 37 | DataClassification = CustomerContent; 38 | } 39 | field(9; webUrl; Text[250]) 40 | { 41 | DataClassification = CustomerContent; 42 | } 43 | } 44 | 45 | keys 46 | { 47 | key(PK; id) 48 | { 49 | Clustered = true; 50 | } 51 | } 52 | } -------------------------------------------------------------------------------- /app.json: -------------------------------------------------------------------------------- 1 | { 2 | "id": "05fe1ea9-a5da-4a2b-a1a0-137542c0f9e8", 3 | "name": "SharePoint Document Explorer", 4 | "publisher": "MSN Raju", 5 | "version": "1.0.0.0", 6 | "brief": "", 7 | "description": "Sample project to demonstrate how to integrate Business Central with SharePoint", 8 | "privacyStatement": "", 9 | "EULA": "", 10 | "help": "", 11 | "url": "https://www.msnjournals.com/post/how-to-connect-sharepoint-with-business-central", 12 | "logo": "media\\msnJournals.png", 13 | "dependencies": [ 14 | { 15 | "id": "63ca2fa4-4f03-4f2b-a480-172fef340d3f", 16 | "publisher": "Microsoft", 17 | "name": "System Application", 18 | "version": "16.0.0.0" 19 | }, 20 | { 21 | "id": "437dbf0e-84ff-417a-965d-ed2bb9650972", 22 | "publisher": "Microsoft", 23 | "name": "Base Application", 24 | "version": "16.0.0.0" 25 | }, 26 | { 27 | "id": "abffecdf-7bf2-4321-ab3f-6ee7fc3b9921", 28 | "publisher": "MSN Raju", 29 | "name": "Universal OAuth 2.0 Authorization", 30 | "version": "1.0.0.0" 31 | } 32 | ], 33 | "screenshots": [], 34 | "platform": "16.0.0.0", 35 | "idRanges": [ 36 | { 37 | "from": 50100, 38 | "to": 50149 39 | } 40 | ], 41 | "contextSensitiveHelpUrl": "https://www.msnjournals.com/post/how-to-connect-sharepoint-with-business-central", 42 | "showMyCode": true, 43 | "runtime": "5.0" 44 | } -------------------------------------------------------------------------------- /src/OnlineDrives.Page.al: -------------------------------------------------------------------------------- 1 | page 50115 "Online Drives" 2 | { 3 | PageType = List; 4 | ApplicationArea = All; 5 | UsageCategory = Administration; 6 | SourceTable = "Online Drive"; 7 | SourceTableTemporary = true; 8 | Editable = false; 9 | 10 | layout 11 | { 12 | area(content) 13 | { 14 | repeater(Control1) 15 | { 16 | ShowCaption = false; 17 | 18 | field("Name"; Rec.Name) 19 | { 20 | ApplicationArea = All; 21 | Caption = 'Name'; 22 | 23 | trigger OnDrillDown() 24 | begin 25 | OpenDriveItems(); 26 | end; 27 | } 28 | field("Drive Type"; Rec.driveType) 29 | { 30 | Caption = 'Type'; 31 | ApplicationArea = All; 32 | } 33 | field("Last Modified DateTime"; Rec.lastModifiedDateTime) 34 | { 35 | Caption = 'Last Modified DateTime'; 36 | ApplicationArea = All; 37 | } 38 | } 39 | } 40 | } 41 | 42 | trigger OnOpenPage() 43 | var 44 | TempOnlineDrive: Record "Online Drive" temporary; 45 | OnlineDriveAPI: Codeunit "Online Drive API"; 46 | begin 47 | AccessToken := OnlineDriveAPI.GetAccessToken('AZUREAD'); 48 | commit; 49 | if OnlineDriveAPI.FetchDrives(AccessToken, TempOnlineDrive) then 50 | Rec.Copy(TempOnlineDrive, true); 51 | end; 52 | 53 | var 54 | AccessToken: Text; 55 | 56 | local procedure OpenDriveItems() 57 | var 58 | OnlineDriveItems: Page "Online Drive Items"; 59 | begin 60 | OnlineDriveItems.SetProperties(AccessToken, '', Id, ''); 61 | OnlineDriveItems.Run(); 62 | end; 63 | } -------------------------------------------------------------------------------- /src/OnlineDriveItems.Page.al: -------------------------------------------------------------------------------- 1 | page 50116 "Online Drive Items" 2 | { 3 | PageType = List; 4 | ApplicationArea = All; 5 | UsageCategory = Administration; 6 | SourceTable = "Online Drive Item"; 7 | SourceTableTemporary = true; 8 | Editable = false; 9 | 10 | layout 11 | { 12 | area(content) 13 | { 14 | group(Title) 15 | { 16 | ShowCaption = false; 17 | Visible = FolderPath <> ''; 18 | 19 | field(Parent; FolderPath) 20 | { 21 | ShowCaption = false; 22 | } 23 | } 24 | 25 | repeater(Control1) 26 | { 27 | ShowCaption = false; 28 | 29 | field("Name"; Rec.Name) 30 | { 31 | ApplicationArea = All; 32 | Caption = 'Name'; 33 | 34 | trigger OnDrillDown() 35 | begin 36 | OpenDriveItems(); 37 | end; 38 | } 39 | field("Is File"; Rec.isFile) 40 | { 41 | Caption = 'Is File'; 42 | ApplicationArea = All; 43 | } 44 | field("Created DateTime"; Rec.createdDateTime) 45 | { 46 | Caption = 'Created DateTime'; 47 | ApplicationArea = All; 48 | } 49 | } 50 | } 51 | } 52 | 53 | actions 54 | { 55 | area(Processing) 56 | { 57 | action("Create a new folder") 58 | { 59 | ApplicationArea = All; 60 | 61 | trigger OnAction() 62 | var 63 | OnlineCreateDriveFolder: Page "Online Create Drive Folder"; 64 | FolderName: Text; 65 | begin 66 | if OnlineCreateDriveFolder.RunModal() = Action::OK then begin 67 | FolderName := OnlineCreateDriveFolder.GetFolderName(); 68 | if FolderName = '' then 69 | exit; 70 | 71 | OnlineDriveAPI.CreateDriveFolder(AccessToken, driveId, parentId, FolderName, Rec); 72 | end; 73 | 74 | end; 75 | } 76 | action("Delete the selected item") 77 | { 78 | ApplicationArea = All; 79 | ShortcutKey = 'shift + f4'; 80 | 81 | trigger OnAction() 82 | begin 83 | if Confirm(ConfirmMsg, false) then 84 | if OnlineDriveAPI.DeleteDriveItem(AccessToken, driveId, id) then 85 | Delete(); 86 | end; 87 | } 88 | action("Upload a File") 89 | { 90 | ApplicationArea = All; 91 | 92 | trigger OnAction() 93 | var 94 | FromFile: Text; 95 | Stream: InStream; 96 | begin 97 | if UploadIntoStream('Select a File', '', '', FromFile, Stream) then 98 | OnlineDriveAPI.UploadFile(AccessToken, driveId, parentId, FolderPath, FromFile, Stream, Rec); 99 | end; 100 | } 101 | } 102 | } 103 | 104 | var 105 | OnlineDriveAPI: Codeunit "Online Drive API"; 106 | AccessToken: Text; 107 | FolderPath: Text; 108 | ConfirmMsg: Label 'Do you want to delete the selected item ?'; 109 | 110 | procedure SetProperties(NewAccessToken: Text; NewFolderPath: Text; DriveID: Text; ParentID: Text) 111 | var 112 | TempOnlineDriveItem: Record "Online Drive Item" temporary; 113 | begin 114 | AccessToken := NewAccessToken; 115 | FolderPath := NewFolderPath; 116 | 117 | if ParentID = '' then 118 | OnlineDriveAPI.FetchDrivesItems(AccessToken, DriveID, TempOnlineDriveItem) 119 | else 120 | OnlineDriveAPI.FetchDrivesChildItems(AccessToken, DriveID, ParentID, TempOnlineDriveItem); 121 | 122 | Rec.Copy(TempOnlineDriveItem, true); 123 | end; 124 | 125 | local procedure OpenDriveItems() 126 | var 127 | OnlineDriveItems: Page "Online Drive Items"; 128 | Stream: InStream; 129 | begin 130 | if not isFile then begin 131 | OnlineDriveItems.SetProperties(AccessToken, StrSubstNo('%1/%2', FolderPath, name), driveId, Id); 132 | OnlineDriveItems.Run(); 133 | end else begin 134 | if OnlineDriveAPI.DownloadFile(AccessToken, driveId, id, Stream) then 135 | DownloadFromStream(Stream, '', '', '', name); 136 | end; 137 | end; 138 | } -------------------------------------------------------------------------------- /src/OnlineDriveAPI.Codeunit.al: -------------------------------------------------------------------------------- 1 | codeunit 50115 "Online Drive API" 2 | { 3 | var 4 | DrivesUrl: Label 'https://graph.microsoft.com/v1.0/drives', Locked = true; 5 | DrivesItemsUrl: Label 'https://graph.microsoft.com/v1.0/drives/%1/root/children', Comment = '%1 = Drive ID', Locked = true; 6 | DrivesChildItemsUrl: Label 'https://graph.microsoft.com/v1.0/drives/%1/items/%2/children', Comment = '%1 = Drive ID, %2 = Item ID', Locked = true; 7 | UploadUrl: Label 'https://graph.microsoft.com/v1.0/drives/%1/items/root:/%2:/content', Comment = '%1 = Drive ID, %2 = File Name', Locked = true; 8 | DownloadUrl: Label 'https://graph.microsoft.com/v1.0/drives/%1/items/%2/content', Comment = '%1 = Drive ID, %2 = Item ID', Locked = true; 9 | DeleteUrl: Label 'https://graph.microsoft.com/v1.0/drives/%1/items/%2', Comment = '%1 = Drive ID, %2 = Item ID', Locked = true; 10 | CreateFolderUrl: Label 'https://graph.microsoft.com/v1.0/drives/%1/items/%2/children', Comment = '%1 = Drive ID, %2 = Item ID', Locked = true; 11 | CreateRootFolderUrl: Label 'https://graph.microsoft.com/v1.0/drives/%1/root/children', Comment = '%1 = Drive ID', Locked = true; 12 | 13 | procedure GetAccessToken(AppCode: Code[20]): Text 14 | var 15 | OAuth20Application: Record "OAuth 2.0 Application"; 16 | OAuth20AppHelper: Codeunit "OAuth 2.0 App. Helper"; 17 | MessageText: Text; 18 | begin 19 | OAuth20Application.Get(AppCode); 20 | if not OAuth20AppHelper.RequestAccessToken(OAuth20Application, MessageText) then 21 | Error(MessageText); 22 | 23 | exit(OAuth20AppHelper.GetAccessToken(OAuth20Application)); 24 | end; 25 | 26 | procedure UploadFile( 27 | AccessToken: Text; 28 | DriveID: Text; 29 | ParentID: Text; 30 | FolderPath: Text; 31 | FileName: Text; 32 | var Stream: InStream; 33 | var OnlineDriveItem: Record "Online Drive Item"): Boolean 34 | var 35 | HttpClient: HttpClient; 36 | Headers: HttpHeaders; 37 | RequestMessage: HttpRequestMessage; 38 | RequestContent: HttpContent; 39 | ResponseMessage: HttpResponseMessage; 40 | JsonResponse: JsonObject; 41 | IsSucces: Boolean; 42 | ResponseText: Text; 43 | begin 44 | Headers := HttpClient.DefaultRequestHeaders(); 45 | Headers.Add('Authorization', StrSubstNo('Bearer %1', AccessToken)); 46 | 47 | RequestMessage.SetRequestUri( 48 | StrSubstNo( 49 | UploadUrl, 50 | DriveID, 51 | StrSubstNo('%1/%2', FolderPath, FileName))); 52 | RequestMessage.Method := 'PUT'; 53 | 54 | RequestContent.WriteFrom(Stream); 55 | RequestMessage.Content := RequestContent; 56 | 57 | if HttpClient.Send(RequestMessage, ResponseMessage) then 58 | if ResponseMessage.IsSuccessStatusCode() then begin 59 | if ResponseMessage.Content.ReadAs(ResponseText) then begin 60 | IsSucces := true; 61 | if JsonResponse.ReadFrom(ResponseText) then 62 | ReadDriveItem(JsonResponse, DriveID, ParentID, OnlineDriveItem); 63 | end; 64 | end else 65 | if ResponseMessage.Content.ReadAs(ResponseText) then 66 | JsonResponse.ReadFrom(ResponseText); 67 | 68 | exit(IsSucces); 69 | end; 70 | 71 | procedure DownloadFile(AccessToken: Text; DriveID: Text; ItemID: Text; var Stream: InStream): Boolean 72 | var 73 | TempBlob: Codeunit "Temp Blob"; 74 | OStream: OutStream; 75 | JsonResponse: JsonObject; 76 | Content: Text; 77 | NewDownloadUrl: Text; 78 | begin 79 | NewDownloadUrl := StrSubstNo(DownloadUrl, DriveID, ItemID); 80 | if GetResponse(AccessToken, NewDownloadUrl, Stream) then 81 | exit(true); 82 | end; 83 | 84 | procedure CreateDriveFolder( 85 | AccessToken: Text; 86 | DriveID: Text; 87 | ItemID: Text; 88 | FolderName: Text; 89 | var OnlineDriveItem: Record "Online Drive Item"): Boolean 90 | var 91 | HttpClient: HttpClient; 92 | Headers: HttpHeaders; 93 | ContentHeaders: HttpHeaders; 94 | RequestMessage: HttpRequestMessage; 95 | RequestContent: HttpContent; 96 | ResponseMessage: HttpResponseMessage; 97 | ResponseText: Text; 98 | JsonBody: JsonObject; 99 | RequestText: Text; 100 | EmptyObject: JsonObject; 101 | JsonResponse: JsonObject; 102 | begin 103 | Headers := HttpClient.DefaultRequestHeaders(); 104 | Headers.Add('Authorization', StrSubstNo('Bearer %1', AccessToken)); 105 | if ItemID = '' then 106 | RequestMessage.SetRequestUri(StrSubstNo(CreateRootFolderUrl, DriveID)) 107 | else 108 | RequestMessage.SetRequestUri(StrSubstNo(CreateFolderUrl, DriveID, ItemID)); 109 | RequestMessage.Method := 'POST'; 110 | 111 | // Body 112 | JsonBody.Add('name', FolderName); 113 | JsonBody.Add('folder', EmptyObject); 114 | JsonBody.WriteTo(RequestText); 115 | RequestContent.WriteFrom(RequestText); 116 | 117 | // Content Headers 118 | RequestContent.GetHeaders(ContentHeaders); 119 | ContentHeaders.Remove('Content-Type'); 120 | ContentHeaders.Add('Content-Type', 'application/json'); 121 | 122 | RequestMessage.Content := RequestContent; 123 | 124 | if HttpClient.Send(RequestMessage, ResponseMessage) then 125 | if ResponseMessage.IsSuccessStatusCode() then begin 126 | if ResponseMessage.Content.ReadAs(ResponseText) then begin 127 | if JsonResponse.ReadFrom(ResponseText) then 128 | ReadDriveItem(JsonResponse, DriveID, ItemID, OnlineDriveItem); 129 | 130 | exit(true); 131 | end; 132 | end; 133 | end; 134 | 135 | procedure DeleteDriveItem(AccessToken: Text; DriveID: Text; ItemID: Text): Boolean 136 | var 137 | HttpClient: HttpClient; 138 | Headers: HttpHeaders; 139 | RequestMessage: HttpRequestMessage; 140 | ResponseMessage: HttpResponseMessage; 141 | begin 142 | Headers := HttpClient.DefaultRequestHeaders(); 143 | Headers.Add('Authorization', StrSubstNo('Bearer %1', AccessToken)); 144 | 145 | RequestMessage.SetRequestUri(StrSubstNo(DeleteUrl, DriveID, ItemID)); 146 | RequestMessage.Method := 'DELETE'; 147 | 148 | 149 | if HttpClient.Send(RequestMessage, ResponseMessage) then 150 | if ResponseMessage.IsSuccessStatusCode() then 151 | exit(true); 152 | end; 153 | 154 | procedure FetchDrives(AccessToken: Text; var Drive: Record "Online Drive"): Boolean 155 | var 156 | JsonResponse: JsonObject; 157 | JToken: JsonToken; 158 | begin 159 | if HttpGet(AccessToken, DrivesUrl, JsonResponse) then begin 160 | if JsonResponse.Get('value', JToken) then 161 | ReadDrives(JToken.AsArray(), Drive); 162 | 163 | exit(true); 164 | end; 165 | end; 166 | 167 | procedure FetchDrivesItems(AccessToken: Text; DriveID: Text; var DriveItem: Record "Online Drive Item"): Boolean 168 | var 169 | JsonResponse: JsonObject; 170 | JToken: JsonToken; 171 | IsSucces: Boolean; 172 | begin 173 | if HttpGet(AccessToken, StrSubstNo(DrivesItemsUrl, DriveID), JsonResponse) then begin 174 | if JsonResponse.Get('value', JToken) then 175 | ReadDriveItems(JToken.AsArray(), DriveID, '', DriveItem); 176 | 177 | exit(true); 178 | end; 179 | end; 180 | 181 | procedure FetchDrivesChildItems( 182 | AccessToken: Text; 183 | DriveID: Text; 184 | ItemID: Text; 185 | var DriveItem: Record "Online Drive Item"): Boolean 186 | var 187 | JsonResponse: JsonObject; 188 | JToken: JsonToken; 189 | IsSucces: Boolean; 190 | begin 191 | if HttpGet(AccessToken, StrSubstNo(DrivesChildItemsUrl, DriveID, ItemID), JsonResponse) then begin 192 | if JsonResponse.Get('value', JToken) then 193 | ReadDriveItems(JToken.AsArray(), DriveID, ItemID, DriveItem); 194 | 195 | exit(true); 196 | end; 197 | end; 198 | 199 | local procedure GetDriveID(var Drive: Record "Online Drive"; Name: Text): Text 200 | begin 201 | Drive.SetRange(Name, Name); 202 | if Drive.FindFirst() then 203 | exit(Drive.Id); 204 | end; 205 | 206 | local procedure GetItemID(var DriveItem: Record "Online Drive Item"; DriveID: Text; Name: Text): Text 207 | begin 208 | exit(GetItemID(DriveItem, DriveID, '', Name)); 209 | end; 210 | 211 | local procedure GetItemID( 212 | var DriveItem: Record "Online Drive Item"; 213 | DriveID: Text; 214 | ItemID: Text; 215 | Name: Text): Text 216 | begin 217 | DriveItem.SetRange(driveID, DriveID); 218 | DriveItem.SetRange(parentId, ItemID); 219 | DriveItem.SetRange(Name, Name); 220 | if DriveItem.FindFirst() then 221 | exit(DriveItem.Id); 222 | end; 223 | 224 | local procedure ReadDrives(JDrives: JsonArray; var Drive: Record "Online Drive") 225 | var 226 | JDriveItem: JsonToken; 227 | JDrive: JsonObject; 228 | JToken: JsonToken; 229 | begin 230 | foreach JDriveItem in JDrives do begin 231 | JDrive := JDriveItem.AsObject(); 232 | 233 | Drive.Init(); 234 | if JDrive.Get('id', JToken) then 235 | Drive.Id := JToken.AsValue().AsText(); 236 | if JDrive.Get('name', JToken) then 237 | Drive.Name := JToken.AsValue().AsText(); 238 | if JDrive.Get('description', JToken) then 239 | Drive.description := JToken.AsValue().AsText(); 240 | if JDrive.Get('driveType', JToken) then 241 | Drive.driveType := JToken.AsValue().AsText(); 242 | if JDrive.Get('createdDateTime', JToken) then 243 | Drive.createdDateTime := JToken.AsValue().AsDateTime(); 244 | if JDrive.Get('lastModifiedDateTime', JToken) then 245 | Drive.lastModifiedDateTime := JToken.AsValue().AsDateTime(); 246 | if JDrive.Get('webUrl', JToken) then 247 | Drive.webUrl := JToken.AsValue().AsText(); 248 | Drive.Insert(); 249 | end; 250 | end; 251 | 252 | local procedure ReadDriveItems( 253 | JDriveItems: JsonArray; 254 | DriveID: Text; 255 | ParentID: Text; 256 | var DriveItem: Record "Online Drive Item") 257 | var 258 | JToken: JsonToken; 259 | begin 260 | foreach JToken in JDriveItems do 261 | ReadDriveItem(JToken.AsObject(), DriveID, ParentID, DriveItem); 262 | end; 263 | 264 | local procedure ReadDriveItem( 265 | JDriveItem: JsonObject; 266 | DriveID: Text; 267 | ParentID: Text; 268 | var DriveItem: Record "Online Drive Item") 269 | var 270 | JFile: JsonObject; 271 | JToken: JsonToken; 272 | begin 273 | 274 | DriveItem.Init(); 275 | DriveItem.driveId := DriveID; 276 | DriveItem.parentId := ParentID; 277 | 278 | if JDriveItem.Get('id', JToken) then 279 | DriveItem.Id := JToken.AsValue().AsText(); 280 | if JDriveItem.Get('name', JToken) then 281 | DriveItem.Name := JToken.AsValue().AsText(); 282 | 283 | if JDriveItem.Get('size', JToken) then 284 | DriveItem.size := JToken.AsValue().AsBigInteger(); 285 | 286 | if JDriveItem.Get('file', JToken) then begin 287 | DriveItem.IsFile := true; 288 | JFile := JToken.AsObject(); 289 | if JFile.Get('mimeType', JToken) then 290 | DriveItem.mimeType := JToken.AsValue().AsText(); 291 | end; 292 | 293 | if JDriveItem.Get('createdDateTime', JToken) then 294 | DriveItem.createdDateTime := JToken.AsValue().AsDateTime(); 295 | if JDriveItem.Get('webUrl', JToken) then 296 | DriveItem.webUrl := JToken.AsValue().AsText(); 297 | DriveItem.Insert(); 298 | end; 299 | 300 | local procedure GetResponse(AccessToken: Text; Url: Text; var Stream: InStream): Boolean 301 | var 302 | Client: HttpClient; 303 | Headers: HttpHeaders; 304 | RequestMessage: HttpRequestMessage; 305 | ResponseMessage: HttpResponseMessage; 306 | RequestContent: HttpContent; 307 | IsSucces: Boolean; 308 | begin 309 | Headers := Client.DefaultRequestHeaders(); 310 | Headers.Add('Authorization', StrSubstNo('Bearer %1', AccessToken)); 311 | 312 | RequestMessage.SetRequestUri(Url); 313 | RequestMessage.Method := 'GET'; 314 | 315 | if Client.Send(RequestMessage, ResponseMessage) then 316 | if ResponseMessage.IsSuccessStatusCode() then begin 317 | if ResponseMessage.Content.ReadAs(Stream) then 318 | IsSucces := true; 319 | end else 320 | ResponseMessage.Content.ReadAs(Stream); 321 | 322 | exit(IsSucces); 323 | end; 324 | 325 | local procedure HttpGet(AccessToken: Text; Url: Text; var JResponse: JsonObject): Boolean 326 | var 327 | Client: HttpClient; 328 | Headers: HttpHeaders; 329 | RequestMessage: HttpRequestMessage; 330 | ResponseMessage: HttpResponseMessage; 331 | RequestContent: HttpContent; 332 | ResponseText: Text; 333 | IsSucces: Boolean; 334 | begin 335 | Headers := Client.DefaultRequestHeaders(); 336 | Headers.Add('Authorization', StrSubstNo('Bearer %1', AccessToken)); 337 | 338 | RequestMessage.SetRequestUri(Url); 339 | RequestMessage.Method := 'GET'; 340 | 341 | if Client.Send(RequestMessage, ResponseMessage) then 342 | if ResponseMessage.IsSuccessStatusCode() then begin 343 | if ResponseMessage.Content.ReadAs(ResponseText) then 344 | IsSucces := true; 345 | end else 346 | ResponseMessage.Content.ReadAs(ResponseText); 347 | 348 | JResponse.ReadFrom(ResponseText); 349 | exit(IsSucces); 350 | end; 351 | } --------------------------------------------------------------------------------