{"id":173,"date":"2019-08-20T13:48:22","date_gmt":"2019-08-20T13:48:22","guid":{"rendered":"https:\/\/raminahmadi.co.uk\/?p=173"},"modified":"2025-07-11T16:25:03","modified_gmt":"2025-07-11T16:25:03","slug":"sharepoint-framework-azure-function-and-react-hooks-where-the-magic-happens-part-1","status":"publish","type":"post","link":"https:\/\/codingwithramin.com\/?p=173","title":{"rendered":"SharePoint Framework, Azure Functions and React Hooks, where the magic happens &#8211; part 1"},"content":{"rendered":"\n<p>We are living in a world which everyday you wake up with some brilliant features added to your favorite libraries and you can&#8217;t wait to use them somewhere in your solution.<\/p>\n\n\n\n<p>In this post I will show you how easy is to call Azure Functions from SharePoint Framework Web Part and also how you can use React Hooks to simplifies your components and get rid of extra classes and life cycles around them.<\/p>\n\n\n\n<p>As you know React Hooks are new addition to React 16.8 and with the release of SharePoint Framework 1.9.1 you can have them by default which is fantastic! Azure Functions also are so popular as they are so useful in many cases, they are cheap and can be implemented really quick even from Azure Portal and without having any editors! also they are really flexible, you can have a function runs on a timer, or can be triggered when a HTTP endpoint is hit, and last but not least they can be secured with AAD.<\/p>\n\n\n\n<p>So let&#8217;s finish the introduction and jump to the implementation, we will create a web part that calls two Azure Functions, one to get the provisioning template and one to apply a provisioning template.<\/p>\n\n\n\n<p>You can find the source code <a href=\"https:\/\/github.com\/AhmadiRamin\/react-site-provisioning-manager\">here<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Azure Functions Code<\/h2>\n\n\n\n<p>Let&#8217;s start from Azure Functions, I use Visual Studio as it has default templates for Azure Functions and gives me ability to publish or debug the solution easily.<\/p>\n\n\n\n<p>Open Visual Studio, open New Project window and select Azure Functions, give it a name and click OK.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"785\" height=\"526\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/NewProjectWindow.png\" alt=\"\" class=\"wp-image-174\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/NewProjectWindow.png 785w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/NewProjectWindow-300x201.png 300w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/NewProjectWindow-768x515.png 768w\" sizes=\"auto, (max-width: 785px) 100vw, 785px\" \/><\/figure>\n\n\n\n<p>In next window select <strong>Azure Functions v1 (.Net Framework)<\/strong> and <strong>Http trigger<\/strong>, then click OK.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"723\" height=\"414\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/AzureFunctionType.png\" alt=\"\" class=\"wp-image-175\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/AzureFunctionType.png 723w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/AzureFunctionType-300x172.png 300w\" sizes=\"auto, (max-width: 723px) 100vw, 723px\" \/><\/figure>\n\n\n\n<p>Right click on dependencies, select Manage NuGet packages, in the browse tab search for SharePointPnPCoreOnline and install it (we need this package to get Azure Active Directory App-Only context):<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"866\" height=\"382\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/pnpcorepackage.png\" alt=\"\" class=\"wp-image-176\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/pnpcorepackage.png 866w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/pnpcorepackage-300x132.png 300w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/pnpcorepackage-768x339.png 768w\" sizes=\"auto, (max-width: 866px) 100vw, 866px\" \/><\/figure>\n\n\n\n<p>Remove function1.cs and create below folder structure for your solution:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"352\" height=\"228\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/folderstructure.png\" alt=\"\" class=\"wp-image-177\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/folderstructure.png 352w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/folderstructure-300x194.png 300w\" sizes=\"auto, (max-width: 352px) 100vw, 352px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Certificate<\/h2>\n\n\n\n<p>This will be used to authenticate your Application against Azure AD, while requesting the App Only access token.&nbsp;<\/p>\n\n\n\n<p>To create a self signed certificate, download <a href=\"http:\/\/raminahmadi.co.uk\/shared\/Create-SelfSignedCertificate.ps1\">Create-SelfSignedCertificate.ps1<\/a>, open PowerShell and run below command:<\/p>\n\n\n\n<pre data-mode=\"powershell\" data-theme=\"twilight\" data-fontsize=\"14\" data-lines=\"Infinity\" class=\"wp-block-simple-code-block-ace\">.\\Create-SelfSignedCertificate.ps1 -CommonName \"NAME\" -StartDate 2019-08-11 -EndDate 2025-08-11 -Password (ConvertTo-SecureString -String \"PASSWORD\" -AsPlainText -Force)<\/pre>\n\n\n\n<ul class=\"wp-block-list\"><li>NAME: your preferred name for the certificate (e.x. ProvisioningApp).<\/li><li>PASSWORD: replace it with your own password and keep it somewhere safe as we need in next steps.<\/li><li>Change the StartDate and EndDate (you can use  Get-Date in PowerShell).<\/li><\/ul>\n\n\n\n<p>This script gives you two files:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>.cer: to be uploaded to your App Registration.<\/li><li>.pfx: copy this file to Cert folder of your solution.<\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Constants<\/h2>\n\n\n\n<p>Constants are immutable values which are known at compile time and do not change for the life of the program.<\/p>\n\n\n\n<p>Under Constants folder create a class called configs and update it with:<\/p>\n\n\n\n<pre data-mode=\"csharp\" data-theme=\"twilight\" data-fontsize=\"14\" data-lines=\"Infinity\" class=\"wp-block-simple-code-block-ace\">namespace ProvisioningApp.Constants\n{\n  public static class Configs\n  {\n    public const string exportedTemplateName = \"PnPProvisioningTemplate.xml\";\n    public const string clientIdKey = \"CLIENTID\";\n    public const string certificatePathKey = \"CERTIFIATE\";\n    public const string passwordKey = \"PASSWORD\";\n    public const string tenantKey = \"TENANT\";\n  }\n}\n<\/pre>\n\n\n\n<p>There are the application settings keys we will setup later on.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Helper<\/h2>\n\n\n\n<p>Under Utils folder, create a class called Helper.cs and update it with:<\/p>\n\n\n\n<pre data-mode=\"csharp\" data-theme=\"twilight\" data-fontsize=\"14\" data-lines=\"Infinity\" class=\"wp-block-simple-code-block-ace\">using Microsoft.SharePoint.Client;\nusing OfficeDevPnP.Core;\nusing System;\nusing ProvisioningApp.Constants;\n\nnamespace ProvisioningApp.Utils\n{\n  public static class Helper\n  {\n    public static ClientContext GetADAppOnlyContext(string siteUrl, string appDirectory)\n    {\n      var authMgr = new AuthenticationManager();\n\n      string certificateName = Environment.GetEnvironmentVariable(Configs.certificatePathKey);\n      string password = Environment.GetEnvironmentVariable(Configs.passwordKey);\n      string clientId = Environment.GetEnvironmentVariable(Configs.clientIdKey);\n      string tenant = Environment.GetEnvironmentVariable(Configs.tenantKey);\n      string certificatePath = $\"{appDirectory}\\\\Cert\\\\{certificateName}\";\n\n      if (string.IsNullOrEmpty(clientId))\n        throw new ArgumentException($\"Missing required environment variable '{Configs.clientIdKey}'\");\n\n      if (string.IsNullOrEmpty(certificateName))\n        throw new ArgumentException($\"Missing required environment variable '{Configs.certificatePathKey}'\");\n\n      if (string.IsNullOrEmpty(password))\n        throw new ArgumentException($\"Missing required environment variable '{Configs.passwordKey}'\");\n\n      if (string.IsNullOrEmpty(tenant))\n        throw new ArgumentException($\"Missing required environment variable '{Configs.tenantKey}'\");\n\n      return authMgr.GetAzureADAppOnlyAuthenticatedContext(siteUrl, clientId, tenant, certificatePath, password);\n    }\n  }\n}\n<\/pre>\n\n\n\n<p>As you can see this class has only one method that returns Client Context we need to perform our operations against SharePoint.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Models<\/h2>\n\n\n\n<p>Under Models folder we have two classes:<\/p>\n\n\n\n<p><strong>LoadProvisioningInfo.cs<\/strong>: defines the properties in the request body we need to get provisioning template:<\/p>\n\n\n\n<pre data-mode=\"csharp\" data-theme=\"twilight\" data-fontsize=\"14\" data-lines=\"Infinity\" class=\"wp-block-simple-code-block-ace\">using System;\nusing System.Collections.Generic;\nusing System.Text;\nusing OfficeDevPnP.Core.Framework.Provisioning.Model;\nnamespace ProvisioningApp.Models\n{\n  public class LoadProvisioningInfo\n  {\n    public string WebUrl { get; set; }\n\n    public Handlers Handlers { get; set; }\n      \n  }\n}\n<\/pre>\n\n\n\n<p>ApplyProvisioningInfo.cs: data we need to apply the provisioning template.<\/p>\n\n\n\n<pre data-mode=\"csharp\" data-theme=\"twilight\" data-fontsize=\"14\" data-lines=\"Infinity\" class=\"wp-block-simple-code-block-ace\">using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nnamespace ProvisioningApp.Models\n{\n  public class ApplyProvisioningInfo\n  {\n    public string WebUrl { get; set; }\n\n    public string Template { get; set; }\n  }\n}\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Functions<\/h2>\n\n\n\n<p>Now we are ready to create out functions, under Functions folder create two Azure Functions:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>GetProvisioningTemplate.cs<\/li><li>ApplyProvisioningTemplate.cs<\/li><\/ul>\n\n\n\n<p>Open GetProvisioningTemplate.cs and paste below code:<\/p>\n\n\n\n<pre data-mode=\"csharp\" data-theme=\"twilight\" data-fontsize=\"14\" data-lines=\"Infinity\" class=\"wp-block-simple-code-block-ace\">using System;\nusing System.Net.Http;\nusing System.Net.Http.Headers;\nusing System.Threading.Tasks;\nusing System.Xml.Linq;\nusing Microsoft.Azure.WebJobs;\nusing Microsoft.Azure.WebJobs.Extensions.Http;\nusing Microsoft.Azure.WebJobs.Host;\nusing Microsoft.SharePoint.Client;\nusing OfficeDevPnP.Core.Framework.Provisioning.Connectors;\nusing OfficeDevPnP.Core.Framework.Provisioning.Model;\nusing OfficeDevPnP.Core.Framework.Provisioning.ObjectHandlers;\nusing OfficeDevPnP.Core.Framework.Provisioning.Providers.Xml;\nusing ProvisioningApp.Models;\nusing ProvisioningApp.Constants;\nusing ProvisioningApp.Utils;\nusing System.IO;\n\nnamespace ProvisioningApp\n{\n  public static class GetProvisioningTemplate\n  {\n    [FunctionName(\"GetProvisioningTemplate\")]\n    public static async Task&lt;HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, \"post\", Route = null)]HttpRequestMessage req, TraceWriter log, ExecutionContext context)\n    {\n      log.Info(\"C# HTTP trigger function processed a request.\");\n      \n      try\n      {\n        var requestBody = await req.Content.ReadAsAsync&lt;LoadProvisioningInfo>();\n\n        if (requestBody == null)\n          return req.CreateResponse(System.Net.HttpStatusCode.BadRequest);\n        \n        GenerateProvisioningTemplate(requestBody,context.FunctionAppDirectory);\n        log.Info(\"Template has been created\");\n        var xDocument = XDocument.Load($\"{Path.GetTempPath()}\\\\{Configs.FileName}\");\n        \/\/ convert the xml into string\n        string xml = xDocument.ToString();\n        var result = new HttpResponseMessage(System.Net.HttpStatusCode.OK);\n        result.Content = new ByteArrayContent(System.Text.Encoding.UTF8.GetBytes(xml));\n        result.Content.Headers.ContentType = new MediaTypeHeaderValue(\"text\/xml\");\n        \n        return result;\n\n      }\n      catch (Exception ex)\n      {\n        return req.CreateErrorResponse(System.Net.HttpStatusCode.InternalServerError,ex.Message);\n      }\n\n    }\n\n    private static void GenerateProvisioningTemplate(LoadProvisioningInfo info, string appDirectory)\n    {\n      var context =  Helper.GetADAppOnlyContext(info.WebUrl, appDirectory);\n\n      using (context)\n      {\n        Web web = context.Web;\n        context.Load(web, w => w.Title);\n        context.ExecuteQueryRetry();\n        ProvisioningTemplateCreationInformation ptci\n                   = new ProvisioningTemplateCreationInformation(context.Web);\n        \n        \/\/ Create FileSystemConnector to store a temporary copy of the template \n        ptci.FileConnector = new FileSystemConnector(Path.GetTempPath(), \"\");\n        ptci.PersistBrandingFiles = true;\n\n        ptci.HandlersToProcess = info.Handlers;\n        \/\/ Execute actual extraction of the template\n        ProvisioningTemplate template = context.Web.GetProvisioningTemplate(ptci);\n\n        \/\/ We can serialize this template to save and reuse it\n        \/\/ Optional step \n        XMLTemplateProvider provider =\n                new XMLFileSystemTemplateProvider(Path.GetTempPath(), \"\");\n        provider.SaveAs(template, Configs.FileName);        \n      }\n    }\n\n    \n\n  }\n}\n<\/pre>\n\n\n\n<p>Couple of notes to mention:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li><strong>ReadAsAsync <\/strong>deserialize&nbsp; the request body to the class we defined (LoadProvisioningInfo).<\/li><li><strong>Path.GetTempPath <\/strong>gives the temporary path in Azure to save your folder (in our case we are going to save the template file as XML).<\/li><li><strong>ProvisioningTemplate<\/strong> class provides everything you need to Get or Apply a provisioning template.<\/li><\/ul>\n\n\n\n<p>Open ApplyProvisioningTemplate.cs and paste this code:<\/p>\n\n\n\n<pre data-mode=\"csharp\" data-theme=\"twilight\" data-fontsize=\"14\" data-lines=\"Infinity\" class=\"wp-block-simple-code-block-ace\">using System;\nusing System.IO;\nusing System.Net;\nusing System.Net.Http;\nusing System.Text;\nusing System.Threading.Tasks;\nusing Microsoft.Azure.WebJobs;\nusing Microsoft.Azure.WebJobs.Extensions.Http;\nusing Microsoft.Azure.WebJobs.Host;\nusing Microsoft.SharePoint.Client;\nusing OfficeDevPnP.Core.Framework.Provisioning.Model;\nusing OfficeDevPnP.Core.Framework.Provisioning.Providers.Xml;\nusing ProvisioningApp.Models;\nusing ProvisioningApp.Utils;\n\nnamespace ProvisioningApp.Functions\n{\n  public static class ApplyProvisioningTemplate\n  {\n    [FunctionName(\"ApplyProvisioningTemplate\")]\n    public static async Task&lt;HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Function, \"post\", Route = null)]HttpRequestMessage req, TraceWriter log, ExecutionContext context)\n    {\n      log.Info(\"C# HTTP trigger function processed a request.\");\n\n      try\n      {\n        var requestBody = await req.Content.ReadAsAsync&lt;ApplyProvisioningInfo>();\n\n        if (requestBody == null)\n          return req.CreateResponse(HttpStatusCode.BadRequest);\n\n        var ctx = Helper.GetADAppOnlyContext(requestBody.WebUrl, context.FunctionAppDirectory);\n        using (ctx)\n        {\n          Web web = ctx.Web;\n          ctx.Load(web, w => w.Title);\n          ctx.ExecuteQueryRetry();\n\n          \/\/ Configure the XML file system provider\n          XMLTemplateProvider provider =\n          new XMLFileSystemTemplateProvider(Path.GetTempPath(), \"\");\n\n          byte[] byteArray = Encoding.ASCII.GetBytes(requestBody.Template);\n          MemoryStream stream = new MemoryStream(byteArray);\n\n          \/\/ Load the template from the XML stored copy\n          ProvisioningTemplate template = provider.GetTemplate(stream);\n\n          \/\/ We can also use Apply-PnPProvisioningTemplate\n          web.ApplyProvisioningTemplate(template);\n        }\n\n        return req.CreateErrorResponse(HttpStatusCode.OK, \"Done!\");\n\n      }\n      catch (Exception ex)\n      {\n        return req.CreateErrorResponse(System.Net.HttpStatusCode.InternalServerError, ex.Message);\n      }\n\n    }\n  }\n}\n<\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Publish functions<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li> If you haven&#8217;t already signed-in to your Azure account from Visual Studio, select Sign-in. <\/li><li> In Solution Explorer, right-click the project and select Publish. <\/li><li> In the Pick a publish target dialog, use the publish options as specified in the table below the image:<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"785\" height=\"591\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/publishprofile.png\" alt=\"\" class=\"wp-image-180\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/publishprofile.png 785w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/publishprofile-300x226.png 300w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/publishprofile-768x578.png 768w\" sizes=\"auto, (max-width: 785px) 100vw, 785px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\"><li> Select Publish. <\/li><li> In the App Service: Create new dialog, enter the hosting settings. <\/li><li> Select Create to create a function app and related resources in Azure with these settings and deploy your function project code. <\/li><\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Securing the Azure function app<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li> Open Azure Portal&nbsp;<a href=\"https:\/\/portal.azure.com\/\">https:\/\/portal.azure.com<\/a>.<\/li><li> Click App Services and find the app you just created.<\/li><li> Click &#8220;Platform features&#8221; tab. <\/li><li> Under Networking, click &#8220;Authentication \/ Authorization&#8221;. <\/li><li> In the option  &#8220;App Service Authentication &#8221; , select  &#8220;ON&#8221;. <\/li><li> For &#8220;Action to take when request is not authenticated&#8221; option, select \u201cLog in with Azure Active Directory\u201d. <\/li><li> Under &#8220;Authentication Providers&#8221;, select \u201cAzure Active Directory\u201d. <\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"693\" height=\"399\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/azureauthentication.png\" alt=\"\" class=\"wp-image-181\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/azureauthentication.png 693w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/azureauthentication-300x173.png 300w\" sizes=\"auto, (max-width: 693px) 100vw, 693px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\"><li> Select \u201cManagement mode\u201d as Express. <\/li><li> Create new AD App or select an existing one. <\/li><li> Click OK and then Save. <\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"591\" height=\"885\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/azureADSettings.png\" alt=\"\" class=\"wp-image-182\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/azureADSettings.png 591w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/azureADSettings-200x300.png 200w\" sizes=\"auto, (max-width: 591px) 100vw, 591px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Setting up the Azure AD app for app-only access <\/h2>\n\n\n\n<p>Now we need to configure our app registration we just created in previous step.<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li> Select Azure Active Director, App Registration and then the App you created.<\/li><li>Click on &#8220;Certificates &amp; secrets&#8221;. <\/li><li> Click on the &#8220;Upload certificate&#8221; button.<\/li><li> Select the .CER file you generated earlier and click on &#8220;Add&#8221; to upload it. <\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"796\" height=\"241\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/uploadcertificate.png\" alt=\"\" class=\"wp-image-183\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/uploadcertificate.png 796w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/uploadcertificate-300x91.png 300w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/uploadcertificate-768x233.png 768w\" sizes=\"auto, (max-width: 796px) 100vw, 796px\" \/><\/figure>\n\n\n\n<ul class=\"wp-block-list\"><li> Click on API Permissions.<\/li><li> Click on the &#8220;Add a permission&#8221; button. <\/li><li> Choose the following permissions: <\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"835\" height=\"682\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/apipermissions.png\" alt=\"\" class=\"wp-image-184\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/apipermissions.png 835w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/apipermissions-300x245.png 300w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/apipermissions-768x627.png 768w\" sizes=\"auto, (max-width: 835px) 100vw, 835px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"> Update App Settings<\/h2>\n\n\n\n<p>We are almost there! from Azure portal open the app service you created,<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li> Click &#8220;Platform features&#8221; tab.<\/li><li> click on &#8220;Configuration&#8221;. <\/li><li>Create new key\/value entries under \u2018App settings\u2019 as per the following table: <\/li><\/ul>\n\n\n\n<table class=\"wp-block-table is-style-stripes\"><tbody><tr><td>Key<\/td><td>Value<\/td><\/tr><tr><td>CERTIFIATE<\/td><td>provisioningapp.pfx<\/td><\/tr><tr><td> PASSWORD <\/td><td> Password you set for the certificate file <\/td><\/tr><tr><td> CLIENTID <\/td><td> Application Registration Client ID<\/td><\/tr><tr><td> TENANT<\/td><td>Your tenant (e.x. contoso.onmicrosoft.com)<\/td><\/tr><\/tbody><\/table>\n\n\n\n<h2 class=\"wp-block-heading\">Enable CORS on Azure Function<\/h2>\n\n\n\n<ul class=\"wp-block-list\"><li> Click Platform features.<\/li><li> Under API, click CORS.<\/li><li> Specify the Office 365 tenant domain url and SharePoint local workbench url.<\/li><li> Click Save.<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"415\" height=\"626\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/CORS.png\" alt=\"\" class=\"wp-image-185\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/CORS.png 415w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/CORS-199x300.png 199w\" sizes=\"auto, (max-width: 415px) 100vw, 415px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Test the functions<\/h2>\n\n\n\n<p>It&#8217;s time to test our functions, there are different ways of testing your functions such as Azure Portal, Postman, Fiddler and other tools as well Visual Studio which gives you ability to debug the code. We are going to test it from Azure Portal:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Open the App Service and select GetProvisioningTemplate function.<\/li><li>Click on Run button:<\/li><li>Add headers and body as below and click Run, if everything is OK you should get response like this:<\/li><\/ul>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"464\" height=\"727\" src=\"https:\/\/raminahmadi.co.uk\/wp-content\/uploads\/2019\/08\/testfunction.png\" alt=\"\" class=\"wp-image-186\" srcset=\"https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/testfunction.png 464w, https:\/\/codingwithramin.com\/wp-content\/uploads\/2019\/08\/testfunction-191x300.png 191w\" sizes=\"auto, (max-width: 464px) 100vw, 464px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p>We&#8217;re now complete with setting up the Azure Functions and they are ready to be called from our SharePoint Framework Web Part, in next part we will discuss the code to call these functions from our web part as well as React Hooks.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We are living in a world which everyday you wake up with some brilliant features added to your favorite libraries and you can&#8217;t wait to use them somewhere in your solution. In this post I will show you how easy is to call Azure Functions from SharePoint Framework Web Part and also how you can use React Hooks to simplifies your components and get rid of extra classes and life cycles around them. As you&hellip;<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[17,5,6,2,4,16],"tags":[9,10,18,7,11],"class_list":["post-173","post","type-post","status-publish","format-standard","hentry","category-azure-functions","category-microsoft-azure","category-microsoft-graph","category-office-365","category-sharepoint-framework","category-visual-studio","tag-azure","tag-azure-function","tag-react-hooks","tag-sharepoint","tag-spfx"],"_links":{"self":[{"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/posts\/173","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=173"}],"version-history":[{"count":6,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/posts\/173\/revisions"}],"predecessor-version":[{"id":205,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=\/wp\/v2\/posts\/173\/revisions\/205"}],"wp:attachment":[{"href":"https:\/\/codingwithramin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=173"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=173"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/codingwithramin.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=173"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}