Search Results for

    Show / Hide Table of Contents

    Advanced PnPContext use

    Requesting a PnPContext is something each application does, using the PnPContextFactory as explained in the overview article. Whereas the overview article describes how to get a PnPContext there are additional possibilities when requesting and working with a PnPContext.

    Adding custom context to a PnPContext

    The PnPContext is at the center of PnP Core SDK and sometimes you might want to add additional context to this object. This can be done by adding your custom context as key value pairs in the PnPContext Properties collection. When a context is cloned (see later chapters on this page), then the added properties are also copied over to the cloned context.

    // Option A: Add some properties after the context was created
    context.Properties.Add("MyProperty", "PnP Rocks!");
    
    // Option B: Add properties during PnPContext creation. If you need the 
    // property as part of throttling event handling then this is the recommended
    // pattern to follow
    
    using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith", 
                                                            new PnPContextOptions()
                                                            {
                                                                Properties = new Dictionary<string, object>
                                                                            {
                                                                                { "MyProperty", "PnP Rocks!" }
                                                                            }
                                                            })
        )
    {
        // Use the context
    }
    
    

    Optimzing performance when you know the exact case of the site to work with

    PnP Core SDK does use a lot of SharePoint batching and that requires that the SharePoint site URIs are used with correct casing inside the batch request. To ensure we know the correct case during PnPContext initialization we do two requests to initialize the context, first one is interactive (that works with invalid casing) and then pick up the correct case from that response, followed by loading the remaining initialization data. If you know the site URI casing you can all the initialization requests in a single roundtrip, to do so specify PnPContextOptions with the SiteUriCasingIsCorrect set to true.

    using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith", 
                                                            new PnPContextOptions()
                                                            {
                                                                SiteUriCasingIsCorrect = true
                                                            })
        )
    {
        // Use the context
    }
    
    

    Loading additional IWeb and ISite properties when creating a PnPContext

    When a PnPContext is created two calls are issued to SharePoint Online. In a first call the IWeb is loaded with following properties: Id, Url and RegionalSettings. In the second call ISite is loaded with the Id and GroupId properties. If your application needs additional IWeb or ISite properties you can optimize the number of server roundtrips by adding the extra needed properties to the already planned requests for loading IWeb and ISite. To do this you can provide a PnPContextOptions object specifying the additional IWeb and ISite properties to load.

    var options = new PnPContextOptions()
    {
        AdditionalSitePropertiesOnCreate = new Expression<Func<ISite, object>>[] { s => s.Url, s => s.HubSiteId },
        AdditionalWebPropertiesOnCreate = new Expression<Func<IWeb, object>>[] { 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.
    }
    

    While above sample just loaded some basic IWeb and ISite properties you can also do more complex LINQ expressions.

    var options = new PnPContextOptions()
    {
        AdditionalSitePropertiesOnCreate = 
            new Expression<Func<ISite, object>>[] { s => s.Url, s => s.HubSiteId,
                                                    s => s.Features },
        AdditionalWebPropertiesOnCreate = 
            new Expression<Func<IWeb, object>>[] 
            {   
                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.
    }
    

    Any expression that you'd normally would write to retrieve data can also be specified to be included in the default context creation.

    Cloning a PnPContext

    Once you've created a PnPContext you might want to clone it for the same site or for a new web.

    Cloning a PnPContext for a new web

    When you clone contexts for a new web the context settings (e.g. GraphFirst) are copied over. If you've specified additional properties to load on context creation these properties will also be loaded for the cloned context. So the cloned context will be exactly configured like the original site, but then for the other web url.

    using (var context = await pnpContextFactory.CreateAsync("SiteToWorkWith"))
    {
        // Clone this context using a configuration
        using (var contextClone = await context.CloneAsync("OtherSite"))
        {
            // Use the cloned context
        }
    
        // Clone this context using a URL
        using (var contextClone = await context.CloneAsync(new Uri("https://contoso.sharepoint.com/sites/anothersite")))
        {
            // Use the cloned context
        }
    }
    

    Cloning a PnPContext for the same web

    Sometimes you want to use a new PnPContext for the same web. You can obviously create a new PnPContext via the context factory, but then you do get the initialization cost again. When you clone a PnPContext the initialization data will be copied across contexts, just like the settings, so you'll get a functioning PnPContext without calling back into SharePoint Online. If you've specified additional properties to load on context creation then only the extra properties which are basic (so no model classes) are copied into the cloned context.

    var options = new PnPContextOptions()
    {
        AdditionalSitePropertiesOnCreate = 
            new Expression<Func<ISite, object>>[] { s => s.Url, s => s.HubSiteId,
                                                    s => s.Features },
        AdditionalWebPropertiesOnCreate = 
            new Expression<Func<IWeb, object>>[] 
            {   
                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))
    {
        // Clone this context using a configuration
        using (var contextClone = await context.CloneAsync("SiteToWorkWith"))
        {
            // Use the cloned context. Without going to the server the default IWeb and ISite properties are loaded
            // + the ISite Url and HubSiteId properties
            // + the IWeb ServerRelativeUrl property
            // Other extra initialization properties are model classes and are not copied over
        }
    }
    
    Back to top PnP Core SDK
    Generated by DocFX with Material UI
    spacer