Sharepoint

SharePoint watcher is easy enough to setup and only requires the Graph authorization details.

The Watcher automatically polls for folder changes within a sharepoint library and gives you an SDK as well as a callback any time a new file is added or changed. You will also get the item in the callback if a field has been updated.

This allows for automated processes to be kicked off any time something within the watched SharePoint directory is modified.

Example Configuration

Here's the fully configured and ready to use snippet of setting this up within Perigee.

PerigeeApplication.ApplicationNoInit("Sharepoint Demo", (taskConfig) =>
    {
        
        taskConfig.AddSharepointWatch("Sharepoint",
            taskConfig.GetValue<string>("Sharepoint:tenant"), 
            taskConfig.GetValue<string>("Sharepoint:appID"),
            taskConfig.GetValue<string>("Sharepoint:appSecret"), 
            taskConfig.GetValue<string>("Sharepoint:site"),
            taskConfig.GetValue<string>("Sharepoint:drivePath"), 
            taskConfig.GetValue<string>("Sharepoint:listName"), 
            (ct, log, api, sync, items) =>
            {
                //Process file here
                return true;
                
            }).LinkToConfig("Sharepoint:enabled");

    });

All of the above are referencing a node in the appsettings.json file, you would need to fill this out with your own authorization details.

"Sharepoint": {
    "tenant": "guid",
    "appID": "guid",
    "appSecret": "secret",
    "drivePath": "",
    "site": "https://mydomain.sharepoint.com/sites/demo/",
    "listName": "Documents",
    "enabled": true
  },
  • tenant/appID/appSecret - These will be pulled from the Azure portal app registration.

  • The drivePath supplied may be blank if you're pulling files from the root of the drive. Otherwise supply the name of the folder to watch.

  • The site key is the full address of the sharepoint site. It's used to perform a graph lookup of the ID records required.

  • The listName is the name of the list behind the drive. If using the default document library, this will be "Documents". If you've created a custom library, something like "Input", then you will need to set the listName to that instead.

  • The enabled flag is to turn the process on or off and is tied to the .LinkToConfig() line above.

SDK & Callbacks

Sync Class - Callback Property

The sync property sent back by the SharePoint watcher contains all of the relevant ID's needed to perform requests within SharePoint. Most importantly:

  • ListID

  • DriveID

  • SiteID

  • SiteName

Items callback

When new items arrive to be processed, you'll get a list of those items in that callback. Each item in the list contains all of the properties you'd need to check the item that was changed.

List<GraphAPIModel.Drive.Children> items;


item.Id;                            // The ID of the item
item.MicrosoftGraphDownloadUrl;     // The URL to download the item
item.Name;                          // The name of the item
item.CreatedBy;                     // The user referencee class of who created it
item.File;                          // If it is a file, this has the file details
item.Folder;                        // If it is a folder, this has the folder details

To see the full list and response please check out the Microsoft documentation

Change Notification

Want to check if the changed notification is a file?

foreach (var item in items)
{
    //Guard change notifications for folders
    if (item.Folder != null || item.File == null) continue;
    
    //Only process file changes
    log?.LogInformation("New file to process from {name} - {item} [{size}]", 
        item.CreatedBy.User.DisplayName, 
        item.Name, 
        item.Size);
}

Get Item + Fields

This call retrieves the item from a drive, and expands the response to include the list detail and fields as well

var details = api.GetItemWithList(sync.siteID, sync.driveID, item.Id);

The list fields are important as they allow you to get the custom field values. In this example, we have a custom field called "Status" that we can update along the process:

var status = details.listItem.fields["Status"];
//Status = "Ready"

Get Item by Path

To get an item if you already have the path.

If expand is true, you'll also receive the list item details along with the response.

api.GetItemByPath(sync.siteID, "Folder/File.txt", expandListItem = true)

Get Item by Path In Drive

To get an item if you already have the path for a given DriveID.

If expand is true, you'll also receive the list item details along with the response.

api.GetItemByPath(DriveID, "Folder/File.txt", expandListItem = true)

You can generate a direct download link to a SharePoint item by giving the Site, library, and path to the item.

The resulting string is generated and uses the SharePoint /Download.aspx page.

api.GenerateSharepointDownloadLink(Site, "Shared Documents", "Folder/File.txt");

Delete an Item

To remove an item by ID:

api.DeleteItem(sync.siteID, ItemID);

Patch a Field

After retrieving the List Details, you can patch any of the fields with the PatchField command:

api.PatchField(sync.siteID, sync.listID, details.listItem.id, 
new { 
    Status = "Success",
    Notes = "We are done!"
    });

Get Another Drive

If you need to get a different drive, say a Processed drive, you can do so by querying for the drive:

var Drives = api.GetSiteDrives(sync.siteID);
var ProcessedDriveID = Drives.Where(f => f.name.Equals("Processed")).FirstOrDefault()?.id ?? "";

Uploading an item

To upload an item to a drive you must supply the DriveID, Name, Content, and MIME Type.

We'll upload a document to the Processed drive as shown here.

var uploaded = api.UploadFile(ProcessedDriveID, 
    "MyZip.zip", new byte[] {0x0}, "application/zip");

//Get the details from the newly uploaded item
var itemDetails = api.GetItemWithList(sync.siteID, ProcessedDriveID, uploaded.Id);

Download an Item

To download an item from SharePoint we highly recommend first getting the List Details as well as it can provide a backup download link. Then simply call download:

if (item.MicrosoftGraphDownloadUrl == null)
{
    //Try resetting it from the details list
    item.MicrosoftGraphDownloadUrl = new Uri(details.DownloadURL);
}

byte[] File = api.DownloadItem(item);

Implementing your own

To call any other method not supplied here use the internal graph call client and supply the right path, the rest will be taken care of automatically.

var response = api.RestGraphCall<GraphAPIModel.Generic.Response>(
    $"/sites/{sync.siteID}/lists/{sync.ListName}", Method.Get);

Last updated