Publish Duplicate Client Side Page Changes To Original Page Within Same SPO Site Pages Library

 

Problem Statement

 
This article is a continuation of my previous article, Duplicate the Client Side Pages into same Modern SharePoint Online Library Folder where I explained how to duplicate the client side page with all existing controls.
 
In this article, I would like to explain this: If the user makes any changes to duplicate page, how to publish the duplicate client side pages to the original page into same site pages library within the same site collection.
 
As a developer, we have a couple of options to duplicate the page into another modern site collection library or different folder structure, but there is no way to copy the pages within the same modern site collection sites library within the same folder structure.
 
Prerequisite Steps
 
Let's create a page and add existing below control, or user can add any other available controls. This is just for demo purposes.
  • SharePoint Online PnP PowerShell Overview here
  • Browse the existing pages
Home Page looks like this,




Duplicate Page looks like this with changes,
  • Add new control
  • Modify the pages control layout





Approach Overview

 
Key steps to publish duplicate client side page with changes to original Modern Site Collection Site Pages into Same Library Folder.
  1. Use PnP Online to connect to SharePoint Online Modern Site
  2. Export PnP Client Side Pages Command export pages with PnP Provisioning Template
  3. Store it locally.
  4. Apply PnP Provisioning Template store it with different name. 
  1. try   
  2.    {  
  3.   
  4.          $srcUrl = "https://mittal1201.sharepoint.com/sites/commsitehub"   
  5.          Connect-PnPOnline -Url $srcUrl  
  6.   
  7.          $SourcePageName = "home_duplicate"  
  8.          $TargetPageName = "home"  
  9.       
  10.          $tempFile = 'C:\CsharpCorner\'+ $SourcePageName +'.xml'  
  11.          Export-PnPClientSidePage -Force -Identity $SourcePageName -Out $tempFile  
  12.   
  13.          $con = Get-Content $tempFile  
  14.          $sourcepage=$SourcePageName +".aspx"  
  15.          $targetpage=$TargetPageName +".aspx"  
  16.        
  17.          $con | % { $_.Replace($sourcepage,$targetpage) } | Set-Content $tempFile  
  18.          Apply-PnPProvisioningTemplate -Path  $tempFile  
  19.          write-host -ForegroundColor Magenta "Page reverted with name of  " $targetpage      
  20.        
  21.      
  22. }   
  23. catch {  
  24.     Write-Host - ForegroundColor Red 'Error '':'  
  25.     $Error[0].ToString();  
  26.      
  27. }  


Save and run this script.
 

OutPut Steps

 
Applying template to client side pages
 

Export-PnPClientSidePage Cmdlets applying the PnP Provisioning template and export ".xml" file into shared locaiton. Cmdlets referece can be find here 



Creation of client side pages
 
Apply-PnPProvisioningTemplate cmdlets will create a new page within the same library from download or exported ".xml" file with provided name i.e. pagename _ duplicate
Cmdlets referece can be find here






Final Duplicate Page Outcome
 
Browse the url; i.e., original page. New Client Side Page will be available with all configuration and controls.




I hope you have enjoyed and learned something new in this article. Thanks for reading and stay tuned for the next article.



Duplicate Client Side Pages Into Same Modern SharePoint Online SitePages Lib

 

Problem Statement 

 
In this article, I would like to explain how to duplicate client side pages which have OOTB webparts and custom SPFx webparts into the same site pages library within the same site collection.
 
As a developer, we have a couple of options to duplicate the page into another modern site collection library or different folder structure, but  there is no way to copy the pages within the same modern site collection site library within the same folder structure.



 
Prerequisites Steps  
 
Let's create a page and add the exisitng below controls,  or the user can add any other available controls. This is just for demo purposes. 
  • SharePoint Online PnP PowerShell Overview here
  • Add and Configure  Custom SPFx Control
  • Add and Configure  Image Control
  • Add and Configure  News Control



Approach Overview

 
We need to follow the below key steps to perform duplication of Modern Site Collection Site Pages into the Same Library Folder. 
  1. Use PnP Online to connect to SharePoint Online Modern Site
  2. Export PnP Client Side Pages Command  export pages with PnP Provisioning Template
  3. Store it locally.
  4. Apply PnP Provisioning Template store it with different name. 
SharePoint Online PnP PowerShell Script

  1. try   
  2.    {  
  3.       
  4.         $srcUrl = "https://mittal1201.sharepoint.com/sites/commsitehub"   
  5.         Connect-PnPOnline -Url $srcUrl  
  6.         $pageName  = [System.Web.HttpUtility]::UrlDecode("Home")  
  7.         write-host $pageName  
  8.         $tempFile = 'C:\CsharpCorner\'+ $pageName +'.xml'  
  9.         Export-PnPClientSidePage -Force -Identity $pageName -Out $tempFile  
  10.   
  11.         $con = Get-Content $tempFile  
  12.         $sourcepage=$pageName +".aspx"  
  13.         $targetpage=$pageName +"_Duplicate.aspx"  
  14.        
  15.         $con | % { $_.Replace($sourcepage, $targetpage) } | Set-Content $tempFile  
  16.         Apply-PnPProvisioningTemplate -Path  $tempFile  
  17.         write-host -ForegroundColor Magenta "Page Created with name of  " $targetpage    
  18.      
  19. }   
  20. catch {  
  21.     Write-Host - ForegroundColor Red 'Error '':'  
  22.     $Error[0].ToString(); 


Save and run this script.

OutPut Steps 

 
Applying template to client side pages
 
Export-PnPClientSidePage Cmdlets applying the PnP Provisioning template and export ".xml" file into shared locaiton. Cmdlets referece can be found here 


Creation of client side pages 
 
Apply-PnPProvisioningTemplate cmdlets will create a new page within same library from download or exported ".xml" file with provided name i.e. pagename _ duplicate
Cmdlets referece can be found here
 



 Final Duplicate Page outcome

 
Browse the url with suffix as _duplicate in the url. New Client Side Page will be available with all configuration and controls.



I hope you have enjoyed and learned something new in this article. Thanks for reading and stay tuned for the next article.


SPFX with DevOps using SharePoint ALM & Blob Storage

Implement SPFx (SharePoint Framework) deployment with DevOps using SharePoint ALM Commands & Blob Storage

Azure DevOps (Visual Studio Team Services / Team Foundation Server) consists of a set of tools and services that help developers implement DevOps, Continuous Integration, and Continuous Deployment processes for their development projects.

This article explains the steps involved in setting up your Azure DevOps environment with Continuous Integration and Continuous Deployment to automate your SharePoint Framework builds, unit tests, and deployment.

SharePoint ALM (Application Life Cycle Management) APIs provide simple APIs to manage deployment of your SharePoint Framework solutions and add-ins across your tenant or Site Collection level.

ALM APIs can be used to perform exactly the same operations that are available from a UI perspective

Continuous Integration

Continuous Integration (CI) helps developers integrate code into a shared repository by automatically build  and packaging the solution each time new code changes are submitted.

Setting up Azure DevOps for Continuous Integration with a SharePoint Framework solution requires the following steps:

Office Azure & SharePoint ALM - Build Pipeline

  • Node 10.x
  • Gulp Clean
  • Gulp Build
  • Gulp Bundle --ship
  • Gulp Package-Solution --ship
  • Publish Build Artifacts  (Task Version 1)
    • "Display Name" -> Publish Artifact: CDN
    • "Path to Publish" -> temp/deploy
    • "Artifact Name" -> CDN
    • "Artifact Publish Location" -> Azure Pipeline
  • Publish Build  Artifact
    • "Display Name" -> Publish Artifact: App
    • "Path to Publish" -> sharepoint/solution
    • "Artifact Name" -> App
    • "Artifact Publish Location" -> Azure Pipeline


Continuous Deployment

Continuous Deployment (CD) takes validated code packages from build process and deploys them into a staging or production environment. Developers can track which deployments were successful or not and narrow down issues to specific package versions.

Setting up Azure DevOps for Continuous Deployments with a SharePoint Framework solution requires the following steps:

  • Office Azure & SharePoint ALM - Build Pipeline
  • Azure file copy (Task Version 2)
    • "Display name"-> AzureBlobFileCopy
    • "Source"->  $(System.DefaultWorkingDirectory)/_AzureDevOpsCI/CDN
    • "AzureConnectionType"-> Azure Resource Manager
    • "Azure Subscription"
    • "Destination Type"-> Azure Blob
    • "RM Storage Account"- > 
    • "Container Name"->
  • SharePoint ALM: Catalog Scoped Actions
    • "Display name"->SharePoint ALM: Add Solution Package
    • "Connection to SharePoint" -> commsite01
    • "Action"-> Add Solution  Package
    • "Path to SharePoint Solution Package"-> $(System.DefaultWorkingDirectory)/_AzureDevOpsCI/App/devops-01.sppkg
    • "
    • "PackageId output variable"-> AppPackageId
  • SharePoint ALM: Catalog Scoped Actions
    • "Display name"->SharePoint ALM: Deploy Solution Package
    • "Connection to SharePoint" -> commsite01
    • "Action"-> Deploy Solution Package
    • "Id of the package in the SharePoint App Catalog"  -> $(AppPackageId)


End to End implementation SPFx deployment using Azure DevOps with SharePoint (Application Life Cycle Management) & Blob Storage for Static files.




SPFX with DevOps using Office 365 CLI

Implement SPFx (SharePoint Framework) deployment with Azure DevOps Pipeline using Office 365 CLI

Azure DevOps (Visual Studio Team Services / Team Foundation Server) consists of a set of tools and services that help developers implement DevOps, Continuous Integration, and Continuous Deployment processes for their development projects.

This article explains the steps involved in setting up your Azure DevOps environment with Continuous Integration and Continuous Deployment to automate your SharePoint Framework builds, unit tests, and deployment.


Continuous Integration

Continuous Integration (CI) helps developers integrate code into a shared repository by automatically build  and packaging the solution each time new code changes are submitted.

Setting up Azure DevOps for Continuous Integration with a SharePoint Framework solution requires the following steps:

  • Office 365 CLI Build Definition
  • Node 10.x
  • Gulp Clean
  • Gulp Build
  • Gulp Bundle --ship
  • Gulp Package-Solution --ship
  • Copy Files
    •  "Display Name" -> Copy Files To: Copy Files to: $(Build.ArtifactStagingDirectory)/drop
    • "Contents" ->  **/*.sppkg
    • "Target Folder" -> $(Build.ArtifactStagingDirectory)/drop
  • Publish Build  Artifact
    • "Display Name" -> Publish Artifact: drop
    • "Publish To Path" -> $(Build.ArtifactStagingDirectory)
    • "Artifact Name"  -> Drop
    • "Artifact Publish Location" -> Azure Pipelines

Continuous Deployment

Continuous Deployment (CD) takes validated code packages from build process and deploys them into a staging or production environment. Developers can track which deployments were successful or not and narrow down issues to specific package versions.

Setting up Azure DevOps for Continuous Deployments with a SharePoint Framework solution requires the following steps:


  • Office 365 CLI Release Pipeline
  • Node 10.x
  • NPM 
    • "Display Name" -> npm custom
    • "Command" -> custom
    • "command and arguments" -> install -g @pnp/office365-cli
  • Command Line
    • "Display Name" -> Connect to SPO
    • "Scripts" -> 
    •  o365 login https://$(tenant).sharepoint.com/$(catalogsite) --authType password --userName $(username) --password $(password)
  • Command Line
    • "Display Name" ->SP add solution
    • "Scripts" -> 
      • o365 spo app add -p $(System.DefaultWorkingDirectory)/_SPFx-AutomateDeployment-CI/drop/drop/sharePoint/solution/clidemo-02.sppkg --overwrite --appCatalogUrl https://$(tenant).sharepoint.com/$(Devcatalogsite) --scope sitecollection
  • Command Line
    • "Display Name" -> Deploy Solution
    • "Scripts" -> 
      • o365 spo app deploy --name clidemo-02.sppkg --appCatalogUrl https://$(tenant).sharepoint.com/$(Devcatalogsite) --scope sitecollection

End to End implementation SPFx deployment with Azure DevOps using Office 365 CLI

 



Adaptive Card Templating With Azure Bot Framework SDKV4

 Adaptive Cards are platform-agnostic snippets of UI, authored in JSON, that apps and services can openly exchange. When delivered to a specific app, the JSON is transformed into native UI that automatically adapts to its surroundings. It helps design and integrate light-weight UI for all major platforms and frameworks.

 
Adaptive Cards Templating is a revolutionary change. It enables the separation of Data & Layouts. 



Let's understand the Adaptive Cards online designer. The designer contains multiple panels that serve different purposes, as shown in the following image:


  1. Card Elements
    List of all elements available for use within Adaptive Cards

  2. Rendered Card
    Preview rendering of the card as it would appear in the currently selected host app.

  3. Card Payload Editor
    The browser-friendly JSON editor contains the source of the Adaptive Card that's rendered in the Rendered Card pane.

  4. Card Structure
    The card is represented in this panel as a hierarchical structure. Notice that as you select elements in this panel, the corresponding control is highlighted in the Rendered Card pane.

  5. Element Properties
    The properties, including those that aren't specified in the source of the Adaptive Card, are displayed in this panel for the control currently selected in the Card Structure panel.

  6. Sample Data Editor
    This panel contains the JSON used when using the templating capability of Adaptive Cards.   
Templating enables the separation of data from layout in your Adaptive Card. The template language is the syntax used to author a template

Binding syntax changed from {...} to ${...} i.e. “text": "Hello {name}" becomes "text": "Hello ${name}"
 
Static Card Payload

  1. {  
  2.    "type""TextBlock",  
  3.    "text""Manoj Mittal"  
  4. }

Template Payload

  1. {  
  2.    "type""TextBlock",  
  3.    "text""${UserName}"  

Let's create bot framework sdkv4 project and associate it with adaptive card templating.
 
Step 1 - Build Bot Framework  SDKV4 C# Project
 
Prerequisties - Azure Bot Framework template installed with Visual Studio 2019.
  • Launch Visual Studio 2019 
  • Select Create new project 
  • Select Azure Bot Framework (.Net Core 2.1 or 3.1) 
  • Create Project.
Step 2 - Create Adaptive Card Template
  • Login to https://adaptivecards.io/designer/
  • Card Element Section desing your card with placehoder, which will be used to bind the data at client side. 
  1. {  
  2.   "$schema""http://adaptivecards.io/schemas/adaptive-card.json",  
  3.   "type""AdaptiveCard",  
  4.   "version""1.2",  
  5.   "body": [  
  6.     {  
  7.       "id""cardHeader",  
  8.       "type""Container",  
  9.       "items": [  
  10.         {  
  11.           "id""planetName",  
  12.           "type""TextBlock",  
  13.           "weight""Bolder",  
  14.           "size""Medium",  
  15.           "text""${name}"  
  16.         }  
  17.       ]  
  18.     },  
  19.     {  
  20.       "type""Container",  
  21.       "id""cardBody",  
  22.       "items": [  
  23.         {  
  24.           "id""planetSummary",  
  25.           "type""TextBlock",  
  26.           "wrap"true,  
  27.           "text""${summary}"  
  28.         },  
  29.         {  
  30.           "id""planetDetails",  
  31.           "type""ColumnSet",  
  32.           "columns": [  
  33.             {  
  34.               "type""Column",  
  35.               "width": 100,  
  36.               "items": [  
  37.                 {  
  38.                   "id""planetImage",  
  39.                   "size""Stretch",  
  40.                   "type""Image",  
  41.                   "url""${imageLink}"  
  42.                 }  
  43.               ]  
  44.             },  
  45.             {  
  46.               "type""Column",  
  47.               "width": 250,  
  48.               "items": [  
  49.                 {  
  50.                   "type""FactSet",  
  51.                   "facts": [  
  52.                     {  
  53.                       "id""orderFromSun",  
  54.                       "title""Order from the sun:",  
  55.                       "value""${id}"  
  56.                     },  
  57.                     {  
  58.                       "id""planetNumSatellites",  
  59.                       "title""Known satellites:",  
  60.                       "value""${numSatellites}"  
  61.                     },  
  62.                     {  
  63.                       "id""solarOrbitYears",  
  64.                       "title""Solar orbit (*Earth years*):",  
  65.                       "value""${solarOrbitYears}"  
  66.                     },  
  67.                     {  
  68.                       "id""solarOrbitAvgDistanceKm",  
  69.                       "title""Average distance from the sun (*km*):",  
  70.                       "value""${solarOrbitAvgDistanceKm}"  
  71.                     }  
  72.                   ]  
  73.                 }  
  74.               ]  
  75.             }  
  76.           ]  
  77.         },  
  78.         {  
  79.           "id""imageAttribution",  
  80.           "type""TextBlock",  
  81.           "size""Small",  
  82.           "isSubtle"true,  
  83.           "wrap"true,  
  84.           "text""${imageAlt}",  
  85.           "weight""Lighter"  
  86.         }  
  87.       ]  
  88.     }  
  89.   ],  
  90.   "actions": [  
  91.     {  
  92.       "type""Action.OpenUrl",  
  93.       "title""Learn more on Wikipedia",  
  94.       "url""${wikiLink}"  
  95.     }  
  96.   ]  
  97. }  


Card will look like this,


Create Folder into Visual Code Project name - Resource.
 
Add Json Template with the name of card.json.



Create Folder into Visual Code Project name - Resource.
 
Add Json Template with the name of card.json.

  1. private readonly string _cards = Path.Combine(".""Resources""Card.json");  
On Message Activity Function, Load Json into template variable

  1. var adaptiveCardJson = (File.ReadAllText(_cards));  
  2.            AdaptiveCardTemplate template = new AdaptiveCardTemplate(adaptiveCardJson);  
Step 4 - Add Data  and bind with template variable
 
Add reference of AdaptiveCards.Templating.  
 
Note
I used static data or hard coded data here for article purposes. Data Json can be rendered via API also.

  1. var adaptiveCardJson = (File.ReadAllText(_cards));  
  2.            AdaptiveCardTemplate template = new AdaptiveCardTemplate(adaptiveCardJson);  
  3.            var myData = new  
  4.            {  
  5.                id = "1",  
  6.                name = "Saturn",  
  7.                summary = "Saturn is the sixth planet from the Sun and the second-largest in the Solar System, after Jupiter. It is a gas giant with an average radius about nine times that of Earth. It has only one-eighth the average density of Earth; however, with its larger volume, Saturn is over 95 times more massive. Saturn is named after the Roman god of wealth and agriculture; its astronomical symbol (♄) represents the god's sickle.",  
  8.                solarOrbitYears = "29.46",  
  9.                solarOrbitAvgDistanceKm = "1433525000",  
  10.                numSatellites = "82",  
  11.                wikiLink = "https://en.wikipedia.org/wiki/Saturn",  
  12.                imageLink = "https://upload.wikimedia.org/wikipedia/commons/c/c7/Saturn_during_Equinox.jpg",  
  13.                imageAlt = "NASA / JPL / Space Science Institute [Public domain]"  
  14.            };  
  15.            string cardJson = template.Expand(myData);  
  16.            var cardAttachment = CreateAdaptiveCardAttachment(cardJson);  
Now turn to render the adaptive card.


  1. private static Attachment CreateAdaptiveCardAttachment(string _card)  
  2.        {  
  3.            var adaptiveCardAttachment = new Attachment()  
  4.            {  
  5.                ContentType = "application/vnd.microsoft.card.adaptive",  
  6.                Content = JsonConvert.DeserializeObject(_card),  
  7.            };  
  8.            return adaptiveCardAttachment;  
  9.        }  
Step 5 - Run Code locally (F5) using Bot Framework Emulator
 
Data and Layout separated while rendering card. Layouts exists at client side and binding of data also happens at client side. As data will come from the API, it  will have server side execution.
 
Earlier we used to bind the Data and Layout at server side and traverse the entire structure. 



Code Base can be downloaded from here.
 
I hope you have enjoyed and learned something new in this article. Thanks for reading and stay tuned for the next article.