pnp / PnP-Sites-Core

Microsoft 365 Dev PnP Core component (.NET) targeted for increasing developer productivity with CSOM based solutions.
Other
415 stars 644 forks source link

Issue with using ApplyTemplates in Azure Function #1474

Open pkbullock opened 6 years ago

pkbullock commented 6 years ago

Category

[* ] Bug [ ] Enhancement

Environment

[* ] Office 365 / SharePoint Online [ ] SharePoint 2016 [ ] SharePoint 2013

PnP NuGet Version: 2.20.1711

Expected or Desired Behavior

Created in Visual Studio 2017 an Azure Function C# with Queue trigger and using PnP Provisioning Apply Provisioning Template code and published run the code without error.

This works with PnP-PowerShell using the same template.

Observed Behavior

Error:

Error applying template: Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. at System.Reflection.RuntimeModule.GetTypes(RuntimeModule module) Application: at System.Reflection.Assembly.GetTypes() Application: at OfficeDevPnP.Core.Framework.Provisioning.Providers.Xml.XmlPnPSchemaBaseSerializer1.DeserializeTemplate(Object persistenceTemplate, ProvisioningTemplate template) Application: at OfficeDevPnP.Core.Framework.Provisioning.Providers.Xml.XmlPnPSchemaBaseSerializer1.ToProvisioningTemplate(Stream template, String identifier) Application: at OfficeDevPnP.Core.Framework.Provisioning.Providers.Xml.XMLPnPSchemaFormatter.ToProvisioningTemplate(Stream template, String identifier) Application: at OfficeDevPnP.Core.Framework.Provisioning.Providers.Xml.XMLTemplateProvider.GetTemplate(String uri, String identifier, ITemplateFormatter formatter, ITemplateProviderExtension[] extensions) Application: at OfficeDevPnP.Core.Framework.Provisioning.Providers.Xml.XMLTemplateProvider.GetTemplate(String uri, ITemplateProviderExtension[] extensions)

Steps to Reproduce

Create an Azure Function in Visual Studio 2017 C# Based (I used a queue trigger) Connect to SharePoint via an App Principal Add code to provision a template using the provisioning engine (sorry cannot share at this time) Got provisioning template from Azure Storage Tried to ApplyProvisioningTemplate but received an error (above)

I might be missing something a dependency from the Azure function but cannot put my finger on what is missing. Do you know or a able to guide in a direction?

Thanks Paul

pkbullock commented 6 years ago

Hi

I have managed to find an answer to my issue on this blog: http://www.techmikael.com/2017/09/resolving-assemblies-when-using-pnp.html

Basically, if you configure Azure Function to use the Managed Service Identity to connect to an Azure KeyVault for credentials, the version of the Microsoft.IdentityModel.Clients.ActiveDirectory is 3.14.2.11

PnP required version 2.29.0 if a newer version is used then the PnP Provisioning engine cannot determine the types (as noted in Mikael blog).

The quickest fix, was to separate the KeyVault credential retrival into a separate project allow for newer assemblies to be used for that feature, and roll back the require assembly in the function project to the version that PnP requires.

It works really well combining, Azure Functions, KeyVault and PnP provisioning.

Paul

anupJag commented 6 years ago

Hi @pkbullock , I too have run into DLL hell with Azure Functions and PnP Provisioning.. Will it be possible for you to post your code here for guidance. Thanks in advance

ravick4u commented 4 years ago

I am also facing the same. I would really appreciate it if someone can post the working code sample here.

Ravikadri-zz commented 4 years ago

Sharing the below code which I have used in Azure function last year. I have used version 3.2.1810 of PnPCoreOnline DLL in Azure function. Below is the partial code. Hope this helps.

 using (var ctx = new AuthenticationManager().GetAppOnlyAuthenticatedContext(SiteURL, CLIENTID, CLIENTSECRET))
            {

                //scoresTable.Execute(TableOperation.Insert(new CustomerEntity("insideappV15", Guid.NewGuid().ToString(), "insideappv15", isApplyPnPTemplateSuccess, null)));

                ctx.RequestTimeout = Timeout.Infinite;
                Web web = ctx.Web;
                ctx.Load(web);
                ctx.ExecuteQuery();
                Console.WriteLine(web.Title + "   Site is connected");
                ctx.Load(web, w => w.Title);
                ctx.ExecuteQueryRetry();

                var xmlprovider = new XMLFileSystemTemplateProvider(TemplateLocation + @"\" + TemplateFolderName, "");
                //test: var xmlprovider = new XMLFileSystemTemplateProvider(@"C:\Users\ravi_\Desktop\Template\SiteDesignTemplates\Blog", "");

                ProvisioningTemplate template1 = xmlprovider.GetTemplate(TemplateFilename);
                //scoresTable.Execute(TableOperation.Insert(new CustomerEntity("Inside Blog", Guid.NewGuid().ToString(), "Inside Blog", isApplyPnPTemplateSuccess, null)));

                var ptai1 = new ProvisioningTemplateApplyingInformation();
                ptai1.ProgressDelegate += (msg, step, total) =>
                {
                    log.Info($"C# Queue trigger function processed:{step}|{total} -  {msg}");

                };
                web.ApplyProvisioningTemplate(template1, ptai1)
            }
ravick4u commented 4 years ago

anyone was able to work around to this?

@andrewconnell