### Install App to a Site Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md Install an app to a specific site using the `InstallAsync` method. This operation is context-specific, so ensure you are using the `PnPContext` instance from the target site. You can install using the app's ID or an app instance. ```csharp // install the app to the site await appManager.InstallAsync(app.Id); // or use app instance await app.InstallAsync(); ``` -------------------------------- ### Install .NET Core SDK on Raspberry Pi Source: https://github.com/pnp/pnpcore/blob/dev/samples/Demo.RPi/README.md Installs the .NET Core SDK on a Raspberry Pi. Ensure you have sufficient permissions and disk space. The script downloads and installs the SDK to a specified directory. ```bash # Download the script from Microsoft wget https://dotnet.microsoft.com/download/dotnet-core/scripts/v1/dotnet-install.sh chmod +x dotnet-install.sh # Ignore warnings ./dotnet-install.sh --channel Current --architecture arm --install-dir ~/ # Allows running dotnet anywhere - thanks to # this article https://edi.wang/post/2019/9/29/setup-net-core-30-runtime-and-sdk-on-raspberry-pi-4 sudo nano .profile export DOTNET_ROOT=$HOME/cli export PATH=$PATH:$HOME/cli ``` -------------------------------- ### Install an App Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md Explains how to install a deployed app into a specific site collection. ```APIDOC ## Install an App To make an app available within a specific site, you must install it using the `InstallAsync` method. ### Install by App ID Installs the app into the current site context using the app's unique ID. ```csharp await appManager.InstallAsync(app.Id); ``` ### Install using App Instance Installs the app into the current site context using the `App` object. ```csharp await app.InstallAsync(); ``` **Important:** The `InstallAsync` operation is context-dependent. Ensure the `PnPContext` used corresponds to the target site where the app should be installed. ``` -------------------------------- ### Install PnP Core SDK and Host Libraries Source: https://github.com/pnp/pnpcore/blob/dev/docs/polyglot/Getting started - interactive login.ipynb Installs the necessary PnP.Core.Auth and Microsoft.Extensions.Hosting libraries from NuGet and sets up using statements for PnP Core SDK. ```csharp #r "nuget: PnP.Core.Auth,*-*" #r "nuget: Microsoft.Extensions.Hosting, 6.0.0" using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using PnP.Core.Auth; using PnP.Core.Services; ``` -------------------------------- ### Install PnP Core Auth and Host Libraries Source: https://github.com/pnp/pnpcore/blob/dev/docs/polyglot/Getting started - application permissions.ipynb Installs the PnP.Core.Auth and Microsoft.Extensions.Hosting libraries from NuGet. Ensure you have the latest versions for compatibility. ```python # Only install PnP.Core.Auth, this will pull in PnP.Core #r "nuget: PnP.Core.Auth,*-*" #r "nuget: Microsoft.Extensions.Hosting, 6.0.0" ``` -------------------------------- ### Setup PnP Core SDK with Application Permissions Source: https://github.com/pnp/pnpcore/blob/dev/docs/polyglot/Getting started - application permissions.ipynb Configures the PnP Core SDK services for application permissions using a certificate. This setup is required before making any PnP Core SDK calls. ```csharp using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using PnP.Core.Auth.Services.Builder.Configuration; using PnP.Core.Services; using PnP.Core.Services.Builder.Configuration; using System.Security.Cryptography.X509Certificates; ``` -------------------------------- ### Automate SharePoint Store app deployment and installation Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md Automates the process of deploying and installing an app from the SharePoint Store using its unique store asset ID. ```APIDOC ## Add and Deploy Store App ### Description Automates the deployment and installation of an app from the SharePoint Store using its unique store asset ID. ### Method ```csharp var tenantAppManager = context.GetTenantAppManager(); var app = tenantAppManager.AddAndDeployStoreApp("WA200001111", CultureInfo.GetCultureInfo(1033).Name, false, true); ``` ### Parameters - **assetId** (string) - The unique store asset ID of the app. - **locale** (string) - The locale of the app to deploy. - **skipFeatureDeployment** (bool) - Whether to skip feature deployment. - **skipAppSideLoading** (bool) - Whether to skip app side-loading. ### Response The method returns an App instance, which can then be used to install the app to any SharePoint site using the apps API. ``` -------------------------------- ### Get Help for Dotnet NuGet Push Source: https://github.com/pnp/pnpcore/blob/dev/build/notes.txt Displays help information for the dotnet nuget push command. ```bash dotnet nuget push --help ``` -------------------------------- ### Build and Serve PNPCoreSDK Test App Source: https://github.com/pnp/pnpcore/blob/dev/src/assets/pnpcoresdk-test-app/README.md Clone the repository, install dependencies, and build the solution. Use `gulp serve` for local development. ```bash git clone the repo npm i npm i -g gulp gulp ``` -------------------------------- ### Getting a File Using a Link Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/files-intro.md Explains how to get an IFile object using a direct link or a sharing link to the file. If the file is in a different site, a new PnPContext is created. ```APIDOC ## GetFileByLinkAsync ### Description Retrieves a file using a fully qualified link or a sharing link. If the file resides in a different site, a new PnPContext is instantiated. ### Method GET ### Endpoint N/A (SDK method) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```csharp // Test regular link IFile file2 = await context.Web.GetFileByLinkAsync($"https://contoso.sharepoint.com/sites/asite/SiteAssets/somefile.docx"); // Test sharing link IFile file1 = await context.Web.GetFileByLinkAsync("https://contoso.sharepoint.com/:v:/s/asite/Ed2UMAoNf0tJhAjSJLt94wYBUd9U-ZhCKOoOXZcGS2dLBQ?e=KobeE5"); // Test sharing link with extra properties of the IFile IFile file1 = await context.Web.GetFileByLinkAsync("https://contoso.sharepoint.com/:v:/s/asite/Ed2UMAoNf0tJhAjSJLt94wYBUd9U-ZhCKOoOXZcGS2dLBQ?e=KobeE5", f => f.CheckOutType, f => f.CheckedOutByUser); ``` ### Response #### Success Response (200) - **IFile** (object) - Represents the file retrieved. #### Response Example (SDK object representation) ``` -------------------------------- ### Install PnP PowerShell Module Source: https://github.com/pnp/pnpcore/blob/dev/docs/tutorials/azurefunctions/v4processisolatedapponly.md Run this command to install the PnP.PowerShell module if you don't already have it. This module is used for configuring Azure AD applications. ```powershell Install-Module -Name PnP.PowerShell ``` -------------------------------- ### Automate SharePoint Store App Deployment and Installation Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md Deploy and install apps from the SharePoint Store programmatically. Requires the unique store asset ID, which can be found in the app's URL. ```csharp var tenantAppManager = context.GetTenantAppManager(); var app = tenantAppManager.AddAndDeployStoreApp("WA200001111", CultureInfo.GetCultureInfo(1033).Name, false, true); ``` -------------------------------- ### Creating an All-Day Event Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/teams-events.md Provides an example of how to create an event that lasts for the entire day using the PnP Core SDK. ```APIDOC ## Adding an event that lasts all day Using the PnP Core SDK, we can add an event that will last all day. ```csharp // Get the Team var team = await context.Team.GetAsync(p => p.Events); // Get the events var events = team.Events; await events.AddAsync(new EventCreateOptions { Subject = "CreateTeamEventThatLastsAllDayAsync", IsAllDay = true, Start = DateTime.Now, End = DateTime.Now.AddDays(1) }); ``` ``` -------------------------------- ### Create PnPContext using Factory Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/upgrade-to-beta3.md Instantiate a PnPContext using the PnPContextFactory. This is the starting point for interacting with the PnP Core SDK. ```csharp using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { } ``` -------------------------------- ### Get Team and Channels with Specific Properties Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/teams-channels.md When loading a team and its channels, specify only the properties you need to populate to optimize performance. ```csharp // Get the Team var team = await context.Team.GetAsync( p => p.Channels.QueryProperties(p => p.DisplayName)); ``` -------------------------------- ### Get Folder by Name Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/files-intro.md Retrieve a specific folder from the web's collection of folders by its name. This example gets the 'SiteAssets' folder. ```csharp // Get root folder of a library IFolder folder = await context.Web.Folders.GetFirstOrDefaultAsync(f => f.Name == "SiteAssets"); ``` -------------------------------- ### Getting a Single File by ID Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/files-intro.md Shows how to retrieve a file using its unique GUID. Similar to getting by URL, you can specify additional properties to load. ```APIDOC ## GetFileByIdAsync ### Description Retrieves a file using its unique identifier (GUID). Allows for selective loading of file properties. ### Method GET ### Endpoint N/A (SDK method) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```csharp Guid fileId = Guid.Parse("{D61B52DE-2ED1-41E2-B3FC-360E7286B0F9}"); // Get a reference to the file IFile testDocument = await context.Web.GetFileByIdAsync(fileId); // Get a reference to the file, loading extra properties of the IFile IFile testDocument = await context.Web.GetFileByIdAsync(fileId, f => f.CheckOutType, f => f.CheckedOutByUser); ``` ### Response #### Success Response (200) - **IFile** (object) - Represents the file retrieved. #### Response Example (SDK object representation) ``` -------------------------------- ### Get Webhook by Id Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/lists-webhooks.md Provides methods to retrieve a specific webhook subscription using its unique identifier (GUID). ```APIDOC ## Get Webhook by Id To get a webhook by its Id, you can use a dedicated method: ```csharp var list = await context.Web.Lists.GetByTitleAsync("My List"); // get by id var webhook = await list.Webhooks.GetByIdAsync(new Guid("")); ``` Alternatively, use LINQ filter: ```csharp var webhookId = new Guid(""); var webhook = await list.Webhooks.FirstOrDefaultAsync(w => w.Id == webhookId); ``` ``` -------------------------------- ### Get Folder by ID Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/folders-intro.md Retrieves a folder using its unique GUID identifier. Ensure you have the correct folder ID. ```csharp // Get a folder by id var folder = await context.Web.GetFolderByIdAsync(new Guid("d50ec969-cb27-4a49-839f-3c25d1d607d5")); ``` -------------------------------- ### Configure and Obtain PnPContext with Authentication Providers Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/readme.md Configure PnP Core SDK and authentication providers without a configuration file. This example demonstrates setting up interactive and username/password authentication, then creating PnPContext instances using these providers. ```csharp var host = Host.CreateDefaultBuilder() .ConfigureServices((context, services) => { services.AddPnPCore(); services.AddPnPCoreAuthentication(options => { options.Credentials.Configurations.Add("interactive", new PnPCoreAuthenticationCredentialConfigurationOptions { ClientId = "c545f9ce-1c11-440b-812b-0b35217d9e83", Interactive = new PnPCoreAuthenticationInteractiveOptions { RedirectUri = new Uri("http://localhost") } }); options.Credentials.Configurations.Add("usernamepassword", new PnPCoreAuthenticationCredentialConfigurationOptions { ClientId = "c545f9ce-1c11-440b-812b-0b35217d9e83", UsernamePassword = new PnPCoreAuthenticationUsernamePasswordOptions { Username = "joe@contoso.onmicrosoft.com", Password = "xxx" } }); }); }) .UseConsoleLifetime() .Build(); await host.StartAsync(); using (var scope = host.Services.CreateScope()) { var pnpContextFactory = scope.ServiceProvider.GetRequiredService(); var pnpAuthenticationProviderFactory = scope.ServiceProvider.GetRequiredService(); var interactiveAuthProvider = pnpAuthenticationProviderFactory.Create("interactive"); var passwordManagerAuthProvider = pnpAuthenticationProviderFactory.Create("usernamepassword"); using (var context = await pnpContextFactory.CreateAsync(new Uri("https://contoso.sharepoint.com/sites/prov-1"), interactiveAuthProvider)) { await context.Web.LoadAsync(p => p.Title); Console.WriteLine($"The title of the web is {context.Web.Title}"); using (var context2 = await pnpContextFactory.CreateAsync(new Uri("https://contoso.sharepoint.com/sites/prov-1"), passwordManagerAuthProvider)) { await context2.Web.LoadAsync(p => p.Title); Console.WriteLine($"The title of the web is {context2.Web.Title}"); } } } ``` -------------------------------- ### Retrieve a Specific Recycled Item Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/recyclebin-intro.md Get a specific item from the recycle bin using its GUID. You can specify which properties to load, such as `LeafName`. ```csharp var doc = await context.Web.GetFileByServerRelativeUrlAsync("/sites/demo/docs/fileA.docx"); // Recycle a document Guid recycleBinItemId = await doc.RecycleAsync(); // Get the recycled document from the recycle bin IRecycleBinItem recycleBinItem = await context.Web.RecycleBin.GetByIdAsync(recycleBinItemId, r => r.LeafName); ``` -------------------------------- ### Get All Apps Acquired from SharePoint Store Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md Retrieve a list of all third-party applications installed from the SharePoint Store. The returned collection supports common app operations. ```csharp var tenantAppManager = context.GetTenantAppManager(); var storeApps = await tenantAppManager.GetStoreAppsAsync(); ``` -------------------------------- ### Example appsettings.demo.json Configuration Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/readme.md This JSON configuration file is used in conjunction with the code-based service configuration to provide custom settings for the PnP Core SDK, including client ID, tenant ID, site URL, and redirect URI. ```json { "CustomSettings": { "ClientId": "{client_id}", "TenantId": "{tenant_id}", "DemoSiteUrl": "https://contoso.sharepoint.com/sites/pnp", "RedirectUri": "http://localhost" }, "Logging": { "LogLevel": { "Default": "Information" } } } ``` -------------------------------- ### Get Tenant App Catalog URL Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md Retrieves the URL for the tenant app catalog site. This is useful for setup tasks to ensure an app catalog site exists. ```APIDOC ### Getting the url for the tenant app catalog site When you're running setup tasks you need to ensure there's an app catalog site setup, using the `GetTenantAppCatalogUri` methods you can get the current tenant app catalog site url: ```csharp // Get the tenant app catalog url, returns null if there's none setup var url = await context.GetTenantAppManager().GetTenantAppCatalogUriAsync(); ``` ``` -------------------------------- ### Add 3rd Party ACE to Viva Dashboard Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/vivaconnections-intro.md Add a third-party Adaptive Card Extension (ACE) to the Viva Connections dashboard. This example shows instantiation using both a typed approach (Option A) and a generic approach (Option B) with a GUID. ```csharp IVivaDashboard dashboard = await context.Web.GetVivaDashboardAsync(); // Instantiate the ACE: Option A var customACE = new AdaptiveCardExtension(); cardDesignerACE.Title = "Custom Async ACE"; cardDesignerACE.Description = "something"; cardDesignerACE.Id = "9e73ef29-1b62-4084-92b5-207bedea22b8"; // Instantiate the ACE: Option B var customACE = dashboard.NewACE(new Guid("9e73ef29-1b62-4084-92b5-207bedea22b8")); customACE.Title = "Custom Async ACE"; customACE.Description = "something"; // Set the ACE properties customACE.Properties = JsonSerializer.Deserialize("{...}"); // Add the ACE to the dashboard as first ACE dashboard.AddACE(customACE); // Persist the dashboard await dashboard.SaveAsync(); ``` -------------------------------- ### Instantiating App Managers Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md Demonstrates how to get instances of the tenant app manager and site collection app manager to interact with app catalogs. ```APIDOC ## Instantiating App Managers To manage apps, you first need to obtain an app manager instance. You can get a tenant-wide app manager or a site collection-specific app manager. ### Tenant App Manager ```csharp var tenantAppManager = context.GetTenantAppManager(); ``` ### Site Collection App Manager ```csharp var siteCollectionAppManager = context.GetSiteCollectionAppManager(); ``` **Note:** For the site collection app manager, ensure you are using the `PnPContext` of the site collection's app catalog. ``` -------------------------------- ### Install ReportGenerator Tool Source: https://github.com/pnp/pnpcore/blob/dev/docs/contributing/writing tests.md Installs the ReportGenerator tool globally, which is used to convert code coverage reports into a human-readable format. Restart shells after installation for the tool to be available. ```bash dotnet tool install -g dotnet-reportgenerator-globaltool ``` -------------------------------- ### Configure PnP Core SDK with Custom Authentication Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/configuring authentication.md Configure PnP Core SDK services and authentication providers. This example shows setting up X.509 certificate authentication with a specific client ID and tenant ID. ```csharp services.AddPnPCore(options => { options.PnPContext.GraphFirst = true; options.HttpRequests.UserAgent = "ISV|Contoso|ProductX"; options.Sites.Add("SiteToWorkWith", new PnPCoreSiteOptions { SiteUrl = "https://contoso.sharepoint.com/sites/pnp" }); }); services.AddPnPCoreAuthentication( options => { // Configure an Authentication Provider relying on Windows Credential Manager options.Credentials.Configurations.Add("x509certificate", new PnPCoreAuthenticationCredentialConfigurationOptions { ClientId = "{your_client_id}", TenantId = "{your_tenant_id}", X509Certificate = new PnPCoreAuthenticationX509CertificateOptions { StoreName = StoreName.My, StoreLocation = StoreLocation.CurrentUser, Thumbprint = "{certificate_thumbprint}" } }); // Configure the default authentication provider options.Credentials.DefaultConfiguration = "x509certificate"; // Map the site defined in AddPnPCore with the // Authentication Provider configured in this action options.Sites.Add("SiteToWorkWith", new PnPCoreAuthenticationSiteOptions { AuthenticationProviderName = "x509certificate" }); }); ``` -------------------------------- ### PnP Core SDK Configuration in appsettings.json Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/readme.md Example `appsettings.json` structure for configuring PnP Core SDK, including telemetry, HTTP requests, PnP context, credentials, and site settings. ```json { "PnPCore": { "DisableTelemetry": "false", "HttpRequests": { "UserAgent": "ISV|Contoso|ProductX", "Timeout": "100", "SharePointRest": { "UseRetryAfterHeader": "false", "MaxRetries": "10", "DelayInSeconds": "3", "UseIncrementalDelay": "true" }, "MicrosoftGraph": { "UseRetryAfterHeader": "true", "MaxRetries": "10", "DelayInSeconds": "3", "UseIncrementalDelay": "true" } }, "PnPContext": { "GraphFirst": "true", "GraphCanUseBeta": "true", "GraphAlwaysUseBeta": "false" }, "Credentials": { "DefaultConfiguration": "interactive", "Configurations": { "interactive": { "ClientId": "{your_client_id}", "TenantId": "{your_tenant_id}", "Interactive": { "RedirectUri": "http://localhost" } } } }, "Sites": { "SiteToWorkWith": { "SiteUrl": "https://contoso.sharepoint.com/sites/pnp", "AuthenticationProviderName": "interactive" }, } } } ``` -------------------------------- ### Deploy App to App Catalog Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md After adding an app, deploy it using the `DeployAsync` method. You can deploy by the app's unique ID or by using an app instance. Specify `skipFeatureDeployment=true` for global deployment. ```csharp var app = await appManager.AddAsync(packagePath, true); // deploy the app using the app's unique id var result = await appManager.DeployAsync(app.Id, false); // deploys app globally using app instance await app.DeployAsync(true); ``` -------------------------------- ### Create Communication Site with Async Provisioning Wait Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-sites.md Creates a communication site and specifies options to wait for the asynchronous provisioning process to complete. Ensure `WaitForAsyncProvisioning` is set to `true` for this behavior. ```csharp var communicationSiteToCreate = new CommunicationSiteOptions(new Uri("https://contoso.sharepoint.com/sites/sitename"), "My communication site") { Description = "My site description", Language = Language.English, }; SiteCreationOptions siteCreationOptions = new SiteCreationOptions() { WaitForAsyncProvisioning = true }; using (var newSiteContext = await context.GetSiteCollectionManager().CreateSiteCollectionAsync(communicationSiteToCreate, siteCreationOptions)) { // Do work on the created site collection via the newSiteContext } ``` -------------------------------- ### Initialize PnPContext Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/lists-intro.md Demonstrates how to create a PnPContext instance using the PnPContextFactory. This context is essential for all subsequent operations with SharePoint. ```csharp using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { // See next chapter on how to use the PnPContext for working with lists } ``` -------------------------------- ### Get Term by ID from Term Set Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/taxonomy-intro.md Fetches a specific term directly from a term set using its ID. This is a direct and efficient way to get a known term. ```csharp // Get a term by id from a term set var term = await termSet.Terms.GetByIdAsync("6b39335d-1975-4fd7-9696-b40d57c9bde7"); ``` -------------------------------- ### Controlled Load of Site and Lists with PnP Core SDK Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/basics-getdata.md Demonstrates loading a Site with its RootWeb properties and controlling the load of its Lists and their Titles. Also shows loading all lists with their content types and field links, and filtering for document libraries. ```csharp using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { // Load the Site with the RootWeb model populated with the Title, NoCrawl and List properties, // for each list load the the Title property await context.Site.LoadAsync(p => p.RootWeb.QueryProperties(p => p.Title, p => p.NoCrawl, p => p.Lists.QueryProperties(p => p.Title))); // Loads all lists with // their content types controlled loaded and // for each content type the field links are controlled loaded // with the name property var lists = await context.Web.Lists.QueryProperties( p => p.Title, p => p.TemplateType, p => p.ContentTypes.QueryProperties( p => p.Name, p => p.FieldLinks.QueryProperties(p => p.Name))) .ToListAsync(); // Loads all document libraries // their content types controlled loaded and // for each content type the field links are controlled loaded // with the name property var lists = await context.Web.Lists.Where(p => p.TemplateType == ListTemplateType.DocumentLibrary) .QueryProperties( p => p.Title, p => p.TemplateType, p => p.ContentTypes.QueryProperties( p => p.Name, p => p.FieldLinks.QueryProperties(p => p.Name))) .ToListAsync(); // Loads the first hidden document library // their content types controlled loaded and // for each content type the field links are controlled loaded // with the name property var list = await context.Web.Lists.Where(p => p.TemplateType == ListTemplateType.DocumentLibrary && p.Hidden) .QueryProperties( p => p.Title, p => p.TemplateType, p => p.ContentTypes.QueryProperties( p => p.Name, p => p.FieldLinks.QueryProperties(p => p.Name))) .FirstOrDefaultAsync(); } ``` -------------------------------- ### Loading and Using Collections Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/basics-getdata.md Demonstrates different ways to load and access collections. Option A loads all lists into the context, while Options B and C work with data loaded into variables or directly enumerated without loading into the context. ```csharp using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { // Option A: Load all lists into the context and use the loaded lists await context.Web.LoadAsync(p => p.Lists); foreach(var list in context.Web.Lists.AsRequested()) { // Use list } // Option B: Use the lists from the returned collection, you're // only working with the effectively returned lists. These lists // are not loaded into the context var lists = await context.Web.Lists.Where(p => p.Title == "Site Pages").ToListAsync(); foreach(var list in lists) { // Use list } // Option C: directly enumerate the lists, these lists are not loaded into the context await foreach(var list in context.Web.Lists) { // Use List } } ``` -------------------------------- ### Initialize PnPContext Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/basics-addupdatedelete.md Demonstrates how to obtain a PnPContext using the PnPContextFactory. This context is essential for all subsequent operations. ```csharp using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { // See next chapter on how to use the PnPContext for adding, updating and deleting data } ``` -------------------------------- ### Initialize PnPContext Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/folders-intro.md Demonstrates how to create a PnPContext using the PnPContextFactory. This context is required for all subsequent operations. ```csharp using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { // See next chapter on how to use the PnPContext for working with folders } ``` -------------------------------- ### Enumerate SharePoint Add-ins in a Site Collection Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-sharepointaddins.md Use this method to retrieve a collection of all SharePoint Add-ins installed within a specific site collection. The returned objects contain installation details. ```csharp var addIns = await context.GetSiteCollectionManager().GetSiteCollectionSharePointAddInsAsync(); foreach(addIn in addIns) { // do something with the AddIn } ``` -------------------------------- ### Configure PnP Core SDK Host with Certificate Authentication Source: https://github.com/pnp/pnpcore/blob/dev/docs/polyglot/Getting started - application permissions.ipynb Set up the host using `PnPCoreAuthenticationX509CertificateOptions` for certificate-based authentication. This involves adding PnP Core SDK services and configuring the authentication credentials. ```csharp // Creates and configures the host var host = Host.CreateDefaultBuilder() .ConfigureServices((context, services) => { // Add PnP Core SDK services.AddPnPCore(options => { // Add the base site url options.Sites.Add("Default", new PnPCoreSiteOptions { SiteUrl = siteUrl }); }); // Manual configure the used authentication services.AddPnPCoreAuthentication(options => { // Load the certificate that will be used to authenticate //var cert = LoadCertificate(certificatePath); // Configure certificate based auth options.Credentials.Configurations.Add("CertAuth", new PnPCoreAuthenticationCredentialConfigurationOptions { ClientId = clientId, TenantId = tenantId, X509Certificate = new PnPCoreAuthenticationX509CertificateOptions { Certificate = LoadCertificate(certificatePath), } }); // Configure the default authentication provider options.Credentials.DefaultConfiguration = "CertAuth"; // Connect the configured authentication method to the configured site options.Sites.Add("Default", new PnPCoreAuthenticationSiteOptions { AuthenticationProviderName = "CertAuth", }); options.Credentials.DefaultConfiguration = "CertAuth"; }); }) .UseConsoleLifetime() .Build(); // Start the host await host.StartAsync(); private static X509Certificate2 LoadCertificate(string certificateThumbprint) { var store = new X509Store(StoreName.My, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); var certificateCollection = store.Certificates.Find(X509FindType.FindByThumbprint, certificateThumbprint, false); store.Close(); return certificateCollection.First(); } ``` -------------------------------- ### Using Model Tokens in Attributes Source: https://github.com/pnp/pnpcore/blob/dev/docs/contributing/model tokens.md Demonstrates various model tokens used within GraphType and GraphProperty attributes to define API request URIs and GET endpoints. These tokens are placeholders that get resolved to actual values at runtime. ```csharp [GraphType(Uri = "teams/{Site.GroupId}")] [GraphProperty("installedApps", Get = "teams/{Site.GroupId}/installedapps?expand=TeamsApp")] ``` ```csharp [GraphType(Uri = "teams/{Parent.GraphId}/channels/{GraphId}")] ``` ```csharp [SharePointType("SP.List", Uri = "_api/Web/Lists(guid'{Id}')", Get = "_api/web/lists", Update = "_api/web/lists/getbyid(guid'{Id}')", LinqGet = "_api/web/lists")] [GraphType(Get = "sites/{Parent.GraphId}/lists/{GraphId}")] ``` ```csharp [GraphProperty("items", Get = "/sites/{Web.GraphId}/lists/{GraphId}/items?expand=fields")] ``` -------------------------------- ### Deploy an App Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md Details how to deploy an app from the app catalog to make it available to sites. This includes options for global deployment. ```APIDOC ## Deploy an App After adding an app to the catalog, you need to deploy it to make it available. The `DeployAsync` method handles this. ### Deploy by App ID Deploys an app using its unique ID. The `skipFeatureDeployment` parameter controls global availability. ```csharp var app = await appManager.AddAsync(packagePath, true); var result = await appManager.DeployAsync(app.Id, false); ``` ### Deploy using App Instance Deploys an app directly using the `App` object. ```csharp var app = await appManager.AddAsync(packagePath, true); await app.DeployAsync(true); ``` Setting `skipFeatureDeployment` to `true` enables global deployment, making the app available across all sites. ``` -------------------------------- ### Efficiently Loading Collections with Async Foreach Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/basics-iqueryable.md Demonstrates an efficient way to load a web's lists using `await foreach`, which requests the collection at the beginning of the loop. Be mindful of potential additional requests if the collection is iterated over again. ```csharp await foreach (var list in context.Web.Lists) { // do something with list here } ``` -------------------------------- ### Get My Followers Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/social-following.md Retrieves a list of all users who are currently following the current user. ```APIDOC ## Get my followers With social following API you can get all current user's followers: ```csharp IList followers = await context.Social.Following.MyFollowersAsync(); ``` ``` -------------------------------- ### Configure PnP Core SDK in Azure Functions Source: https://github.com/pnp/pnpcore/blob/dev/docs/tutorials/azurefunctions/v4processisolatedapponly.md Replace the contents of the `Main()` method in `Program.cs` to add and configure PnP Core SDK services, including site configuration and certificate-based authentication. ```csharp public static void Main() { AzureFunctionSettings azureFunctionSettings = null; var host = new HostBuilder() .ConfigureFunctionsWorkerDefaults() .ConfigureServices((context, services) => { // Add our global configuration instance services.AddSingleton(options => { var configuration = context.Configuration; azureFunctionSettings = new AzureFunctionSettings(); configuration.Bind(azureFunctionSettings); return configuration; }); // Add our configuration class services.AddSingleton(options => { return azureFunctionSettings; }); // Add and configure PnP Core SDK services.AddPnPCore(options => { // Add the base site url options.Sites.Add("Default", new PnPCoreSiteOptions { SiteUrl = azureFunctionSettings.SiteUrl }); }); services.AddPnPCoreAuthentication(options => { // Load the certificate to use X509Certificate2 cert = LoadCertificate(azureFunctionSettings); // Configure certificate based auth options.Credentials.Configurations.Add("CertAuth", new PnPCoreAuthenticationCredentialConfigurationOptions { ClientId = azureFunctionSettings.ClientId, TenantId = azureFunctionSettings.TenantId, X509Certificate = new PnPCoreAuthenticationX509CertificateOptions { Certificate = LoadCertificate(azureFunctionSettings), } }); // Connect this auth method to the configured site options.Sites.Add("Default", new PnPCoreAuthenticationSiteOptions { AuthenticationProviderName = "CertAuth", }); }); }) .Build(); host.Run(); } private static X509Certificate2 LoadCertificate(AzureFunctionSettings azureFunctionSettings) { // Will only be populated correctly when running in the Azure Function host string certBase64Encoded = Environment.GetEnvironmentVariable("CertificateFromKeyVault"); if (!string.IsNullOrEmpty(certBase64Encoded)) { // Azure Function flow return new X509Certificate2(Convert.FromBase64String(certBase64Encoded), "", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.EphemeralKeySet); } else { // Local flow var store = new X509Store(StoreName.My, StoreLocation.CurrentUser); store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly); var certificateCollection = store.Certificates.Find(X509FindType.FindByThumbprint, azureFunctionSettings.CertificateThumbprint, false); store.Close(); return certificateCollection.First(); } } ``` -------------------------------- ### Get User By ID Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/security-users.md Verify if a specific user exists on the site by their unique ID. ```csharp var foundUser = await context.Web.GetUserByIdAsync(userId); ``` -------------------------------- ### Get Current User Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/security-users.md Retrieve the currently logged-in user's information for the site. ```csharp var currentUser = await context.Web.GetCurrentUserAsync(); ``` -------------------------------- ### Typical Test Class Structure Source: https://github.com/pnp/pnpcore/blob/dev/docs/contributing/writing tests.md Demonstrates the basic structure of a test class, including class initialization and a sample test method that uses REST to interact with SharePoint. It shows how to obtain a PnPContext and perform assertions. ```csharp [TestClass] public class GetTests { [ClassInitialize] public static void TestFixtureSetup(TestContext context) { // Configure mocking default for all tests in this class, unless override by a specific test //TestCommon.Instance.Mocking = false; } #region Tests that use REST to hit SharePoint [TestMethod] public async Task GetSinglePropertyViaRest() { //TestCommon.Instance.Mocking = false; using (var context = await TestCommon.Instance.GetContextAsync(TestCommon.TestSite)) { var web = await context.Web.GetAsync(p => p.WelcomePage); // Is the property populated Assert.IsTrue(web.IsPropertyAvailable(p => p.WelcomePage)); Assert.IsTrue(!string.IsNullOrEmpty(web.WelcomePage)); // Are other properties still not available Assert.IsFalse(web.IsPropertyAvailable(p => p.Title)); } } } ``` -------------------------------- ### Get Current User's Followers Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/social-following.md Retrieve a list of all users who are following the current user. ```csharp IList followers = await context.Social.Following.MyFollowersAsync(); ``` -------------------------------- ### Build PnP.Core Project Source: https://github.com/pnp/pnpcore/blob/dev/build/notes.txt Builds the PnP.Core project with a specified version suffix. Use --verbosity n for minimal output. ```bash dotnet build ..\src\sdk\PnP.Core\PnP.Core.csproj --verbosity n --version-suffix preview1 ``` ```bash dotnet build ..\src\sdk\PnP.Core\PnP.Core.csproj --verbosity n /p:Version=0.1.2005.1-preview1 ``` ```bash dotnet build ..\src\sdk\PnP.Core\PnP.Core.csproj --no-incremental /p:Version=0.1.2005.1-preview1 ``` -------------------------------- ### Follow a Tag Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/social-following.md Follow a tag by providing its GUID. The result indicates the outcome of the follow operation. ```csharp // follow a tag var result = await context.Social.Following.FollowAsync(new FollowTagData { TagGuid = new Guid("4fd0d107-8df7-4ace-bffc-72aa0f9a736a") }); ``` -------------------------------- ### Get User Suggestions Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/social-following.md Provides a list of suggested users that the current user might be interested in following. ```APIDOC ## Get user suggestions It's possible to get the list of users, who the current user might want to follow: ```csharp IList suggestions = await context.Social.Following.MySuggestionsAsync(); ``` ``` -------------------------------- ### Create PnPContext Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/changes-sharepoint.md Demonstrates how to create a PnPContext using the PnPContextFactory. This is a prerequisite for most PnP operations. ```csharp using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { // See next chapter on how to use the PnPContext for working with files } ``` -------------------------------- ### Get People Followed By a User Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/social-following.md Returns a collection of people that a specified user is following. This is the inverse of `GetFollowersForAsync`. ```APIDOC ## Gets the people who the specified user is following As an opposite to `GetFollowersFor`, the below method returns a collection of people, who the specified user is following: ```csharp var accountName = "i:0#.f|membership|admin@m365x790252.onmicrosoft.com"; IList followers = await context.Social.Following.GetPeopleFollowedByAsync(accountName); ``` ``` -------------------------------- ### Initialize PnPContext Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/listitems-intro.md Demonstrates how to obtain a PnPContext using the PnPContextFactory. This context is essential for all subsequent operations with the PnP Core SDK. ```csharp using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { // See next chapter on how to use the PnPContext for working with list items } ``` -------------------------------- ### Create PnPContext Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/basics-getdata.md Demonstrates how to create a PnPContext using the PnPContextFactory. This context is the entry point for interacting with Microsoft 365 resources. ```csharp using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { // See next chapter on how to use the PnPContext for requesting data } ``` -------------------------------- ### Get Followers for a User Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/social-following.md Retrieve a list of people who are following a specified user, identified by their account name. ```csharp var accountName = "i:0#.f|membership|admin@m365x790252.onmicrosoft.com"; IList followers = await context.Social.Following.GetFollowersForAsync(accountName); ``` -------------------------------- ### Configure PnP Core SDK Services with appsettings.json Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/readme.md Configure PnP Core SDK services using `AddPnPCore` and `AddPnPCoreAuthentication` extension methods, with settings loaded from `appsettings.json`. ```csharp var host = Host.CreateDefaultBuilder() // Configure logging .ConfigureServices((hostingContext, services) => { // Add the PnP Core SDK library services services.AddPnPCore(); // Add the PnP Core SDK library services configuration from the appsettings.json file services.Configure(hostingContext.Configuration.GetSection("PnPCore")); // Add the PnP Core SDK Authentication Providers services.AddPnPCoreAuthentication(); // Add the PnP Core SDK Authentication Providers configuration from the appsettings.json file services.Configure(hostingContext.Configuration.GetSection("PnPCore")); }) // Let the builder know we're running in a console .UseConsoleLifetime() // Add services to the container .Build(); ``` -------------------------------- ### Get List Fields Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/fields-intro.md Retrieve fields for a specific list, such as the 'Documents' library. This loads the IFieldCollection for the list. ```csharp // Get documents library with fields loaded var documents = await context.Web.Lists.GetByTitleAsync("Documents", l => l.Fields); foreach(var field in documents.Fields.AsRequested()) { // do something with the field } ``` -------------------------------- ### Obtain PnPContext Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/branding-intro.md Demonstrates how to create a PnPContext instance for interacting with a SharePoint site. This context is essential for all subsequent PnP SDK operations. ```csharp using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith")) { // See next chapter on how to use the PnPContext for working with pages } ``` -------------------------------- ### Get Item by ID with CSOM Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/basics-csom-vs-pnp.md Retrieves a list item by its ID using CSOM and executes the query. ```csharp using (var csomContext = new ClientContext(siteUrl)) { var item = csomContext.Web.Lists.GetByTitle("AddTest").GetItemById(1); csomContext.Load(item); csomContext.ExecuteQuery(); } ``` -------------------------------- ### Getting Tenant Properties Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-tenant.md Retrieve a comprehensive list of properties that define how your SharePoint Online tenant operates. ```APIDOC ## Getting the tenant properties There are more than hundred properties that control how a tenant operates and using the `GetTenantProperties` methods you can request these properties: ```csharp var tenantProperties = await context.GetSharePointAdmin().GetTenantPropertiesAsync(); if (tenantProperties.BlockMacSync) { // syncing from Mac devices is blocked } ``` ``` -------------------------------- ### Instantiate Tenant and Site Collection App Managers Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md Use the `GetTenantAppManager` or `GetSiteCollectionAppManager` extension methods to create instances for managing tenant or site collection app catalogs respectively. Ensure the correct context is used for site collection app managers. ```csharp // instantiate a class to work with various tenant app catalog related operations var tenantAppManager = context.GetTenantAppManager(); // instantiate a class to work with various site collection app catalog related operations var siteCollectionAppManager = context.GetSiteCollectionAppManager(); ``` -------------------------------- ### Load Additional IWeb and ISite Properties on Create Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/basics-context.md Optimize PnPContext creation by specifying extra IWeb and ISite properties to load, reducing server roundtrips. This is useful when default properties are insufficient. ```csharp var options = new PnPContextOptions() { AdditionalSitePropertiesOnCreate = new Expression>[] { s => s.Url, s => s.HubSiteId }, AdditionalWebPropertiesOnCreate = new Expression>[] { w => w.ServerRelativeUrl } }; using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith", options)) { // the created context has besides the default properties also the Url and HubSiteId ISite properties loaded + // the ServerRelativeUrl IWeb property. } ``` ```csharp var options = new PnPContextOptions() { AdditionalSitePropertiesOnCreate = new Expression>[] { s => s.Url, s => s.HubSiteId, s => s.Features }, AdditionalWebPropertiesOnCreate = new Expression>[] { w => w.ServerRelativeUrl, w => w.Fields, w => w.Features, w => w.Lists.QueryProperties(r => r.Title, r => r.RootFolder.QueryProperties(p => p.ServerRelativeUrl)) } }; using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith", options)) { // the created context has besides the default properties also the Url, HubSiteId and Features ISite // properties loaded + the ServerRelativeUrl, Fields, Features, Lists with RootFolder IWeb properties. } ``` -------------------------------- ### Delete Folder Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/folders-intro.md A folder can be deleted using the `DeleteAsync` method. This example first creates a folder and then deletes it. ```csharp // Get the root folder of the Site Pages library IFolder folder = (await context.Web.Lists.GetByTitleAsync("Site Pages", p => p.RootFolder)).RootFolder; // Add a folder var subFolder = await folder.Folders.AddAsync("My folder"); // Delete the folder again await subFolder.DeleteAsync(); ``` -------------------------------- ### Creating a New Test Case Source: https://github.com/pnp/pnpcore/blob/dev/docs/contributing/writing tests.md Provides a template for creating a new test case. It includes setting up the PnPContext, optionally disabling mocking for online testing, and demonstrates how to obtain multiple contexts within a single test if needed. ```csharp [TestMethod] public async Task NameOfYourTestMethod() { TestCommon.Instance.Mocking = false; using (var context = await TestCommon.Instance.GetContextAsync(TestCommon.TestSite)) { // here comes your actual test code using (var context1 = await TestCommon.Instance.GetContextAsync(TestCommon.TestSite, 1)) { // here comes your actual test code, eg code that validates what was created in the first part } } } ``` -------------------------------- ### Get User Suggestions for Following Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/social-following.md Retrieve a list of suggested users that the current user might be interested in following. ```csharp IList suggestions = await context.Social.Following.MySuggestionsAsync(); ``` -------------------------------- ### Ensure Tenant App Catalog Exists Source: https://github.com/pnp/pnpcore/blob/dev/docs/using-the-sdk/admin-sharepoint-apps.md Create the tenant app catalog site if it does not exist. The default path is '/sites/appcatalog'. Returns true if the catalog was created, false otherwise. ```csharp // Get the tenant app catalog url, returns null if there's none setup if (await context.GetTenantAppManager().EnsureTenantAppCatalogAsync()) { // App catalog site was missing, but now added as /sites/appcatalog } else { // The app catalog site was already available } ```