Showing posts with label CSOM. Show all posts
Showing posts with label CSOM. Show all posts

April 8, 2021

Access Events from Shared Calendar Using Exchange Web Service and Store Events Data to SharePoint List with C# Console Application

Introduction:

We implemented the intranet solution for a consulting firm based out of Alpharetta, GA, USA. One of the requirements was to store events from Shared Outlook Calendar (Office 365) to SharePoint List for easier accessibility for the users. In this blog, we will learn how to get events from a Shared Outlook Calendar using Microsoft Exchange web service and store in SharePoint Online List with CSOM using C# console application.

So, now Let’s get started with the procedure to build the custom console application.

Step 1: Create Solution

  1.  Open Visual Studio 2019, Click on Create New Project and then Choose Console App (.NET Framework).
  2.  Give it a meaningful Project Name and in Framework select .NET Framework 4 and click "Create".


Step 2: Establish Connectivity with Microsoft Exchange Webservice

  1. Install "Microsoft.Exchange.WebServices" NuGet package.
  2. Add namespace “using Microsoft.Exchange.WebServices.Data;”
  3. We will be using Exchange Service class to connect the Shared Calendar.
  4. We can use the below piece of code to create the instance of ExchangeService and define the credentials & endpoint URL.
     ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);  
     service.Credentials = new WebCredentials("userEmailAddress", "userPassword");  
     service.Url = new Uri("https://outlook.office365.com/ews/exchange.asmx");  
    

Step 3: Get Calendar Events

  1. The calendar can contain some folder, with the use of the "FolderView" class we can retrieve the same. Constructor FolderView(100) Initializes a new instance of the FolderView class with the maximum number of returned folders specified.
     FolderView view = new FolderView(100);
    

  2. Initialize a new instance of the FolderId class with the specified folder name and mailbox.
     FolderId folderToAccess = new FolderId(WellKnownFolderName.Calendar, "shared Email");  
     FolderId(WellKnownFolderName, Mailbox)  
    Use this constructor to link this folder ID to a well-known folder (for example, Inbox, Calendar or Contacts) in a specific mailbox.

  3. FindFoldersResults Represents the results of a folder search operation.
     FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.Root, view);  
    
    FindFolders Obtains a list of folders by searching the subfolders of the specified folder.

  4. CalendarFolder Represents a folder that contains appointments.
     var calendar2 = CalendarFolder.Bind(service,folderToAccess);  
    
    CalendarFolder.Bind(service,folderToAccess) binds to an existing calendar folder and loads its first-class properties. Calling this method results in a call to Exchange Web Services (EWS).

  5. Define a date range view of appointments in the calendar folder search operations.
     CalendarView cv = new CalendarView(StartDate, EndDate);  

  6. FindAppointments obtains a list of appointments by searching the contents of a specified folder.
     FindItemsResults<Appointment> fapts = service.FindAppointments(folderToAccess, cv);  
    
    FindItemsResults<Appointment> a collection of appointments that represents the contents of the specified folder.

    Now with the use of appointment class property, we can retrieve Event Subject, Organizer, and other property.

  7. Here, we will get the Event Title and Organizer.

Step 4: Store in SharePoint List.

  1. Once we get data, we can store it in SharePoint List with CSOM. We will add the Event subject and Organizer Name, for that we create one Single Line of Text and one Person column in a SharePoint List.
  2. Add namespace “using Microsoft.SharePoint.Client;” and “using System.Security;”.
  3. Represents the context for SharePoint objects and operations.
     ClientContext clientContext = new ClientContext(siteUrl);  
    

  4. Give Email and Password, Gets or sets the authentication information for the client context
     clientContext.Credentials = new SharePointOnlineCredentials("username", "password");  
    

  5. Connect List.
     List appointmentsList = clientContext.Web.Lists.GetByTitle("Appointments");  
    

  6. ListItemCreationInformation specifies the properties of the new list item.
     ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation();  
    
    ListItem represents an item or row in a list.

  7. List.AddItem method returns a ListItem instance representing the creation of a new list item in the list.
     ListItem newItem = appointmentsList.AddItem(itemCreateInfo);  
    

  8.  As we know to add items in Person columns into the list, we need to provide Id, below code, will get Id of the organizer.
     var demo = Appoint.Organizer;  
     string testName = demo.ToString();  
     var demo2 = testName.Substring(0, testName.IndexOf("<") - 1);  
     User userTest = clientContext.Web.EnsureUser(demo2);  
     clientContext.Load(userTest);  
     clientContext.ExecuteQuery();  
    

  9. Now, the final step to insert a record into the SharePoint list.
     newItem["Title"] = Appoint.Subject;  
     newItem["Users"] = userTest.Id;  
     newItem.Update();  
     clientContext.ExecuteQuery();  
    

Complete Code

 using System;  
 using Microsoft.Exchange.WebServices.Data;  
 using Microsoft.SharePoint.Client;  
 using System.Security;  
 using Folder = Microsoft.Exchange.WebServices.Data.Folder;  
 namespace SharedCalender  
 {  
 class Program  
 {  
 static void Main(string[] args)  
 {  
 ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010);  
 service.Credentials = new WebCredentials("userEmailAddress", "userPassword");  
 service.Url = new Uri("https://outlook.office365.com/ews/exchange.asmx");  
 FolderView view = new FolderView(100);  
 FolderId folderToAccess = new FolderId(WellKnownFolderName.Calendar, "shared Email");  
 FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.Root, view);  
 foreach (Folder f in findFolderResults)  
 {  
 var calendar2 = CalendarFolder.Bind(service,folderToAccess);  
 DateTime StartDate = DateTime.Today.AddMonths(-1);  
 DateTime EndDate = DateTime.Today.AddMonths(1);  
 CalendarView cv = new CalendarView(StartDate, EndDate);  
 FindItemsResults<Appointment> fapts = service.FindAppointments(folderToAccess, cv);  
 if (fapts.Items.Count > 0)  
 {  
 foreach (Appointment Appoint in fapts)  
 {  
 string siteUrl = "https://constoso.sharepoint.com/sites/SiteName";  
 ClientContext clientContext = new ClientContext(siteUrl);  
 SecureString passWord = new SecureString();  
 foreach (char c in "Password".ToCharArray()) passWord.AppendChar(c);  
 clientContext.Credentials = new SharePointOnlineCredentials("userEmailAddress", passWord);  
 List appointmentsList = clientContext.Web.Lists.GetByTitle("TestList");  
ListItemCreationInformation itemCreateInfo = new ListItemCreationInformation(); ListItem newItem = appointmentsList.AddItem(itemCreateInfo);
//get user id var demo = Appoint.Organizer; string testName = demo.ToString(); var demo2 = testName.Substring(0, testName.IndexOf("<") - 1); User userTest = clientContext.Web.EnsureUser(demo2); clientContext.Load(userTest); clientContext.ExecuteQuery(); newItem["Title"] = Appoint.Subject; newItem["Users"] = userTest.Id; newItem.Update(); clientContext.ExecuteQuery() } } Console.ReadLine(); } } } }

Conclusion:

This is how we can access Events from Shared Calendar using Exchange web service and store data to SharePoint list.

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

November 12, 2020

How to perform Azure App Only Authentication with SharePoint in .Net Core (Azure Function)

Introduction:

In the .NET Framework, there were native classes like  "SharePointCredentials" and "AuthenticatinoManager" which were used for SharePoint Authentication, but now they are removed.

The major difference compared to the .NET Framework CSOM is that the authentication is completely independent of the CSOM library now.

Resolution:

.NET standard CSOM now uses the OAuth for authentication. So we need to get an access token and pass it along with the call to SharePoint Online.

So in this blog, we will learn how to perform Azure App-Only Authentication with SharePoint in new .NET Standard CSOM to get data from SharePoint Online.

When we are using App-Only Authentication, we will have two options:
1. Azure Active Directory App Registration with the client certificate.
2. Create SharePoint App using AppRegNew.aspx and AppInv.aspx.

Here we will discuss the Azure AD App Registration approach.

Step 1:

  • First, we need to register a new app in the Azure Active Directory.
  • Go to http://portal.azure.com/ and select "Azure Active Directory". Now from the "App registrations" option in the left panel, register a new app.


Step 2:

Now we will grant the required permission to the app we created in Step 1. Open the newly created app and click on "API permissions" and click on "Add a permission".

Now select "SharePoint permission" as per your requirement and grant the admin consent. Here we needed "Full Control" permission for SharePoint so we have added "Sites.FullControl.All" and "Sites.Manage.All" permissions.


Step 3:

    1. CertificateName.cert
    2. CertificateName.pfx
  • Consideration: Keep note of the password which you have used to generate a certificate.

Step 4:

  • Now we will configure this certificate with our Azure AD App. 
  • Go to your Azure AD App. Now click on "Certificates and client" from the left panel and click on the "Upload certificate" button.
  • On clicking the "Upload certificate", it will open a panel at the top and allows you to upload the file. Here you need to upload the ".cert" file.

Step 5:

  • Make sure you have selected all required permissions in API Permissions and admin consent has been granted for all required permissions.

Step 6:

  • Now we will create an Azure Function solution using Visual Studio 2019.


Step 7:


Step 8:

  • Now in the Azure Function solution, we need to read the ".pfx" file which is uploaded in our solution. To read the file from the Azure Function solution we need execution context.
  • We can get the execution context using the below parameter in the Azure Function:
          
 ExecutionContext executionContext  

  • Below is the code snippet for how to use execution context:
 [FunctionName("Function1")]  
 public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log, ExecutionContext executionContext)  

  • Now using this execution context, we can get the ".pfx" file as below:
 var Sfilepath = $"{ System.IO.Directory.GetParent(executionContext.FunctionDirectory).FullName}\\Certificate\\CertificateFilename.pfx";  

  • Here we have uploaded the file in the Certificate folder. So the Sfilepath variable we are reading a file from the Certificate folder.

Step 9:

  • Now we will get ClientContext using this Certificate File and Application ID.
  • To get the context, first, we need an access token.
  • To get the access token we need Application ID, Certificate File Path, Certificate File Password, Tenant ID, and Permission Scope.
  • Permission scope will be as below:
  public static string[] permissionscopes = { "https://tenantname.sharepoint.com/.default" };  

  • We will use the below method to get the access token:
 internal static async Task<string> GetApplicationAuthenticatedClient(string clientId, string Sfilepath, string certificatePassword, string[] scopes, string tenantId)  
     {  
       X509Certificate2 certificate = new X509Certificate2(certThumprint, certificatePassword", X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet);  
       IConfidentialClientApplication clientApp;  
       clientApp = ConfidentialClientApplicationBuilder  
       .Create(clientId)  
       .WithCertificate(certificate)  
       .WithTenantId(tenantId)  
       .Build();  
       AuthenticationResult authResult = await clientApp.AcquireTokenForClient(scopes).ExecuteAsync();  
       string accessToken = authResult.AccessToken;  
       return accessToken;  
     }  

  • We can call the above method as below:
 var accessToken = await GetApplicationAuthenticatedClient(clientId, Sfilepath, certificatePassword, permissionscopes, tenantId);  

  • Now the "accessToken" variable will contain the access token.

Step 10:

  • Now using the access token which we get in Step 8, we will generate client context.
  • We can use the below method, which will return the client context. We will need the Site URL for which we want the client context and the access token.
 public static ClientContext GetClientContextWithAccessToken(string targetUrl, string accessToken)  
     {  
       ClientContext clientContext = new ClientContext(targetUrl);  
       clientContext.ExecutingWebRequest +=  
       delegate (object oSender, WebRequestEventArgs webRequestEventArgs)  
       {  
         webRequestEventArgs.WebRequestExecutor.RequestHeaders["Authorization"] =  
   "Bearer " + accessToken;  
       };  
       return clientContext;  
     }  

  • We can call the above method as below:
 var clientCtx = GetClientContextWithAccessToken(siteUrl, accessToken);  

Step 11:

  • Now we have the client context of the Site URL which you have used in step 9.
  • So we can now use the client context for any operations we want to perform programmatically with CSOM.
 Web web = clientCtx.Web;  
 clientCtx.Load(web);  
 clientCtx.ExecuteQuery();  

Conclusion:

This is how we can authenticate to SharePoint from .Net Core with the use of Azure App-Only Authentication. 

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