June 30, 2022

Invite External Users to a SharePoint Site / Add External Users to a SharePoint Group via Power Automate

Introduction

In this blog, we will demonstrate how we can programmatically add external users to a SharePoint Group without using Azure Application and User.Invite.All permission with the help of Power Automate. 

Solution

Firstly, we will create a JSON object that will contain the data that we need to add a new external user to a SharePoint Group as shown in the below image. 

Replace the highlighted content in the object below:

 {   
  "url": "https://tenantname.sharepoint.com/sites/sitename",   
  "peoplePickerInput": "[{\"Key\":\"Email Address\",\"DisplayText\":\"Email Address\",\"IsResolved\":true,\"Description\":\"Email Address\",\"EntityType\":\"\",\"EntityData\":{\"SPUserID\":\"Email Address\",\"Email\":\"Email Address\",\"IsBlocked\":\"False\",\"PrincipalType\":\"UNVALIDATED_EMAIL_ADDRESS\",\"AccountName\":\"Email Address\",\"SIPAddress\":\"Email Address\",\"IsBlockedOnODB\":\"False\"},\"MultipleMatches\":[],\"ProviderName\":\"\",\"ProviderDisplayName\":\"\"}]",   
  "roleValue": "group:GroupID",   
  "sendEmail": true,   
  "emailBody": "",   
  "includeAnonymousLinkInEmail": false,   
  "useSimplifiedRoles": true   
 }   
Set the Email Address of the external user that you want to add to the SharePoint Group.  

Set the GroupID of the SharePoint Group to which you want to add the user. 


Now that we have created the JSON string with the required data, the next step will be to add this JSON to the Request Body and send the request as shown in the below image.



In the "Send an HTTP request to SharePoint" action fill the details as per below:
 Site Address: https://tenantname.sharepoint.com/sites/sitename   
 Method: Post   
 Uri: _api/SP.Web.ShareObject   
 Headers:    
 {   
  "accept": "application/json;odata=verbose",   
  "content-type": "application/json;odata=verbose"   
 }   
 Body: Output of Compose Action   
The flow can now be tested. Once the flow instance has succeeded the invite is sent to the external user. After the external user accepts the invite, the user should be automatically redirected to the SharePoint site with the appropriate access. 

Conclusion

By using this HTTP Post Request, we can invite an external user to any SharePoint Site without any need of the Azure App and any mandatory permissions such as User.Invite.All (which requires Admin Consent). Hope this helps!

If you have any questions you can reach out our SharePoint Consulting team here.

June 23, 2022

SharePoint Framework (SPFx) - How to add Request Header while using PnP for SharePoint List CRUD Operations?

Introduction:

In this blog we will learn how can we add the Request Header while using PnP in SharePoint Framework (SPFx) web parts.

Problem Statement:

When we use the Fetch or Ajax requests in SPFx, we have option to add the Request Header to the REST API requests we are using, but when using PnP, there is no option to add the Request Header while performing CRUD operations in SharePoint.

For example, while using Fetch Request to get the list items, we can add the header as give in below code snippet:
 return fetch(APIUrl, {  
    credentials: 'same-origin',  
    headers: {   
         'Accept': 'application/json;odata=verbose',  
         'odata-version': ''   
    }  
   })  
    .then((res) => res.json())  
    .then((result) => {      
     return result.d.results;  
    },  
     (error) => {  
      console.error('Error:', error);  
     }  
    );  

But, to get the list items using PnP, we will use below code and we will not have option to add the headers:
 await web.lists.getByTitle('List Title').items.select("Title").then((response) => {  
    this.setState({ SiteTimeZoneOnly: response[0].TimeZone });  
 });  

Resolution:

How to add headers:

Step 1) Go to the .ts file of your web part.

Step 2) Now, go to the onInit method.

Step 3) Now, we can add the header in onInit method as given in below code snippet:
 protected onInit(): Promise<void> {  
   return super.onInit().then(_ => {  
    // other init code may be present  
    sp.setup({  
     spfxContext: this.context,  
     sp: {  
      headers: {  
        "X-ClientTag": "********"  
      }  
     }  
    });  
   });  
  }  

Here we have added 'X-ClientTag' header. You can also add comma separated multiple headers as shown in the below code snippet.
 sp.setup({  
     spfxContext: this.context,  
     sp: {  
      headers: {  
        "X-ClientTag": "********",  
        "Accept": "application/json;odata=verbose"  
      }  
     }  
    });  

Now your header is added successfully. You can verify the headers from Network tab of browser developer tool as shown in the below screenshot:

Conclusion:

This is how we can add Request Header in SPFx while using PnP to perform SharePoint list/library operations.

If you have any questions you can reach out our SharePoint Consulting team here.

June 16, 2022

How to apply Site Logo in SharePoint Site using Power Automate?

Introduction:

In this blog, we will learn how can we apply the site logo to SharePoint Site using Power Automate.

We can follow the steps explained below to apply site logo using Power Automate.

Steps:

Step 1: Add action for Send an HTTP request to SharePoint as shown in the below screenshot.

Step 2: Now, in this action, select the fields as given below:
Site Address: Select the site collection where you want to apply the site logo.
Method: POST
Uri: _api/web
Headers: 
              accept: application/json;odata=verbose
              content-type: application/json;odata=verbose
              X-HTTP-Method: MERGE
Body: 
{  
      '__metadata': { type: 'SP.Web' },  
      'SiteLogoUrl': 'https://*******.sharepoint.com/SiteAssets/logo.png'
   }

In SiteLogoUrl, we need to enter the URL of the logo image.

Here is the screenshot of all selected values in Send an HTTP request to SharePoint action.

Step 3: Now, when this flow triggers, the logo will be applied to the site.

Conclusion:

This is how we can apply logo in SharePoint site using Power Automate. Hope this blog will be helpful!

If you have any questions you can reach out our SharePoint Consulting team here.

April 28, 2022

SharePoint - Document Property Promotion and Demotion Feature - How this works, issue & resolution

Introduction

Recently we implemented a SharePoint based solution for a Postal and Parcel company based out of Melbourne, Victoria, Australia. We worked with multiple SharePoint document libraries for our project. Once we came across a scenario when we upload a document, then the document's metadata gets auto-populated or it becomes blank for some specific scenarios and document types.


In this blog, we will learn about this issue, why it gets blank for some specific scenarios and document types, and also we will understand the relationship between the issue and the Document Property Promotion and Demotion feature associated with the document library. 

Issue

  • When we upload a new document to the SharePoint document library the metadata properties get selected automatically which was not the expected behavior for the document library.
  • When we upload an existing document, it was overwriting some of the properties and was clearing out the values for some of the properties.
  • We wanted an experience to be like when the user uploads a new document it should have blank values for its properties. And, if the user uploads an existing document the document should maintain its properties. 

Solution

    • To resolve this issue, we tested the upload process with different document types like docx, xlsx, .pptx, .pdf, .jpg, .png etc. 
    • We faced this issue with office documents only like Word Documents, Excel Files, etc. 
    • We came to know that SharePoint provides a feature called Document Properties Promotion and Demotion. 
    • This feature is responsible for auto-setting the document’s properties when we upload the document to the document library. 
    • If we create a new document, it won't have any metadata associated with it. 
    • And, if we download an existing MS Office document from a SharePoint Document Library that document will be downloaded with its metadata properties and when we upload the same document to a document library then its metadata will get overwritten for that item after the document gets uploaded successfully. 
    • To resolve this issue, we can erase the metadata associated with the document before uploading it to the document library as shown below. 

    Step 1: 

    Open the document in MS office and go to the File Info menu and click on the Check for issues option. 

    Step 2: 

    Expand the Check for issues and click on the Inspect Document as shown below. 

    Step 3: 

    It will open the Document Inspector. Now, click on the Inspect button as shown below.

    Step 4: 

    Now, click on the Remove all button as shown below. 
    • By performing the above steps, we can remove the metadata values associated with the document. 
    • The Document Property Promotion and Demotion feature causes this behavior of copying and storing the document's metadata while downloading it. And overwriting its metadata while uploading that same document again in the library. 
    • We can disable the Document Property Promotion and Demotion feature for SharePoint on-premises but we can't disable this feature for SharePoint Online.  
    • But, This feature is very useful apart from this issue. For example, when we copy the file from one document library to another document library and if the destination library contains similar columns, it will copy-paste the document metadata automatically. We won't need to update it manually. 

    Conclusion

    This is how we can resolve the Document Property Promotion and Demotion feature’s issue. Hope this helps you. 

    If you have any questions you can reach out our SharePoint Consulting team here.

    April 21, 2022

    How to use Multi-Value Taxonomy Picker Control in the SPFx webpart?

    Introduction

    Recently we implemented an SPFx web part solution for a Postal and Parcel company based out of Melbourne, Victoria, Australia. We came across a requirement to provide a taxonomy picker control to select the terms for the term set and to store it in the SharePoint list/library. 


    There are two ways to store the taxonomy picker's selected value in the SharePoint List/Library based on whether it is a single value or multi-value taxonomy picker. 


    We have already shared the details on how to use the single value taxonomy picker control in our previous blog. It can be accessed here.


    In this blog, we will learn about multi-value taxonomy picker control and how to use it in the SPFx web part and store its selected term value with other properties/fields in the SharePoint list/library.

    Pre-Requisites

    • We need to have a multi-value selectable managed metadata column associated with a term set in the SharePoint list. 
    • We need to have the @pnp/spfx-controls-react package installed in our SPFx web part. We can use the command below to install the package. 
     npm install @pnp/spfx-controls-react --save --save-exact  
    

    • Create the context and siteUrl props in the SPFx solution. 
    • Create a state of Array type to store the selected taxonomy picker’s value. 

    Implementation

      Below are the steps to implement the Taxonomy Picker Control for the multi-value managed metadata column. 

      Step 1: 

      Import the taxonomy picker and IPickerTerms in the .tsx(file that contains the render method) file of the SPFx web part as shown below. 

       import { TaxonomyPicker, IPickerTerms } from "@pnp/spfx-controls-react/lib/TaxonomyPicker";   
      

      Step 2: 

      Implement the Taxonomy Picker Control in the render method as shown below. 
      <TaxonomyPicker
           allowMultipleSelections={true}
           termsetNameOrID="Job Title"
           panelTitle="Select Job Title"
           label=""
           context={this.props.context}
           onChange={this.onJobtitleTaxPickerChange.bind(this)}
           isTermSetSelectable={false}
           initialValues={this.state.setJobTitletaxonomy}
           />
      


      Below are the attributes used in the Taxonomy Picker Control.

      • allowMultipleSelections: This attribute is used for multi-value selection. Please provide value as "true" in order to work with the multi-value taxonomy picker control.
      • panelTitle: We need to provide the Term Set Picker Panel title.
      • Label: We need to provide the text displayed above the Taxonomy Picker. Context: We need to provide the content of the current web part. For example, this.props.context.
      • TermsetNameOrID: We need to provide the term set's name or its GUID.
      • OnChange: This attribute is used to store the selected term in a state so we can use that state's value while submitting The item to the SharePoint list/library. It's an optional attribute. 
      • InitialValues: This attribute is used to set the taxonomy picker's selected values. It's an optional attribute. 

      Step 3: 

      After creating taxonomy control, we need to define a method to handle its on-change event and store the selected term in a state as shown below. 

        private onJobtitleTaxPickerChange(terms: IPickerTerms) {
          this.setState({
            setJobTitletaxonomy: terms
          });
        } 
      

      Step 4: 

      The managed metadata column has a single line of text hidden column associated with it, it's a hidden field and we will use this field with its internal name for the further process. We can retrieve the internal name of the hidden field of the managed metadata column using the below rest API 

       http://<sitecollection>/<site>/_api/web/Lists/getbytitle(List Title)/items(itemid)/fieldValuesAsText   

      Here, we have to provide the site address, List title, and item Id of one of the list items. For Example:

       https://binaryrepublik.sharepoint.com/sites/blog/_api/web/Lists/getbytitle('Blog')/items(1)/fieldValuesAsText   
      

      We will get the response from the Rest API as shown below. 


      We will use this column in our program for storing the managed metadata column's value.  

      Step 5: 

      When we use the Rest API to store values to the SharePoint List/Library we need to pass the details in the body of the rest API and to provide the details for managed metadata column we need to use the below format.

          var JobTitle = "";
          this.state.setJobTitletaxonomy.forEach((element, index) => {
            if (index == 0) {
              JobTitle += "-1;#" + element.name + "|" + element.key + ";";
            }
            else {
              JobTitle += "#-1;#" + element.name + "|" + element.key + ";";
            }
          });
          if (this.state.setJobTitletaxonomy.length > 0) {
            bodyArray["fc4c63d6c6ce4056ae9a66b7db5f5564"] = JobTitle;
          }  

      Here, we have used the setJobTitletaxonomy state for the managed metadata column. Now we can use the above body array to the body of the SharePoint rest API call. 

      Step 6: 

      Below is the detailed code for retrieving the values and submitting them to create a new item to the SharePoint List/Library. Submit method of the SPFx form: 

         //getValues() is used to retrieve the request digest value for creating items using the rest API call. 
        public getValues(site): any {
          try {
            var url = site + '/_api/contextinfo';
            return fetch(url, {
              method: "POST",
              headers: { Accept: "application/json;odata=verbose", "Content-Type": 'application/json;odata=verbose', 'Access-Control-Allow-Origin': '*' },
              credentials: "same-origin"
            }).then((response) => {
              return response.json();
            });
          } catch (error) {
            console.log("getValues: " + error);
          }
        }
        //CreteItem() is used to create an item in the SharePoint list.   
        public createItem() {
          let bodyArray = {};
          bodyArray['__metadata'] = {
            "type": "SP.Data.BlogListItem"
          },
          bodyArray['Title'] = "Ajay Varma";
          var JobTitle = "";
          this.state.setJobTitletaxonomy.forEach((element, index) => {
            if (index == 0) {
              JobTitle += "-1;#" + element.name + "|" + element.key + ";";
            }
            else {
              JobTitle += "#-1;#" + element.name + "|" + element.key + ";";
            }
          });
          if (this.state.setJobTitletaxonomy.length > 0) {
            bodyArray["fc4c63d6c6ce4056ae9a66b7db5f5564"] = JobTitle;
          }
          let jsonBodyArray = JSON.stringify(bodyArray);
          var url = this.props.siteUrl + `/_api/web/lists/getbytitle('Blog')/items()`;
          return new Promise<any>((resolve, reject) => {
            try {
              this.getValues(this.props.siteUrl).then((token) => {
                fetch(url,
                  {
                    method: "POST",
                    credentials: 'same-origin',
                    headers: {
                      Accept: 'application/json',
                      "Content-Type": "application/json;odata=verbose",
                      "X-RequestDigest": token.d.GetContextWebInformation.FormDigestValue,
                    },
                    body: jsonBodyArray,
                  }).then((r) => {
                    return r.status != 204 ?
                      r.json() : r.status;
                  })
                  .then((response) => {
                    resolve(response);
                    return response;
                  })
                  .catch((error) => {
                    reject(error);
                  });
              }, (error) => {
                console.log(error);
                reject(error);
              });
            }
            catch (e) {
              console.log(e);
              reject(e);
            }
          });
        }
      

      Results:

      Side Panel for Taxonomy Picker:

      This is the Taxonomy Picker's Panel that retrieves the terms from the term set and displays them as shown below.

      SPFx web part: 

      Once we select and save the term for the Taxonomy Picker it will be added to the Taxonomy Picker field as shown below.

      SharePoint List: 

      The SharePoint List/Library will store the values as shown below.

      Conclusion: 

      This is how we can use the multi-value taxonomy picker. Hope this helps you. 

      If you have any questions you can reach out our SharePoint Consulting team here.