sharepoint online – Authenticate a C # / WPF app with CSOM and Client ID / Client Secret

I've developed a desktop application that accesses our company's SharePoint Online Web site to use multiple lists. Currently, this app uses username / password credentials to obtain an auth cookie, which will then be used for each subsequent access. This auth cookie expires only when the user changes their password, prompting them to reenter their new password and obtain the new auth cookie.

Now, enterprise IT has decided to abandon this "legacy authentication" and switch to "modern authentication". As a result, my application will no longer be able to access our website, as username and password credentials will no longer be accepted.

I now look at modern methods of authentication with our SharePoint Online site that lead me to using application-specific methods Client ID and Client Secret,

First, how (if at all possible) can I authenticate my app with ClientID/ClientSecret? I would really appreciate a snippet of code that (if possible) is based on nothing else than CSOM, I have already learned it SharePointPnPCoreOnline Package and confirmed that it works, but it depends on a large number of other packages that I do not need to distribute with my app. In addition, after authentication, any action that this app performs on a list should be recorded as being in the context of the user running the app (CreatedBy/ModifiedBy Columns should have the actual user running the app).

Second, if this is not possible with CSOM, I have begun to investigate the use of it MSAL.NET (which seems to be the recommended method), but nothing I've found so far has led me to solve my problem explained above. Again, I would welcome a snippet of code that represents the entire process of this type of authentication.

If using ClientID / ClientSecret is not your best bet, I'd like to know what other options I have for my WPF application to correctly authenticate and use CSOM.

UPDATE 1 – Use as reference SharePointPnPCoreOnline package, this is the code segment that worked:

AuthenticationManager mgr = new AuthenticationManager();
using (var context = mgr.GetWebLoginClientContext("https://mycompany.sharepoint.com/sites/MySite"))
{
    context.Load(context.Web, web => web.Title);
    context.ExecuteQuery();
    Console.WriteLine(context.Web.Title);
    Console.ReadKey();
}

This will bring up a window for a few seconds, and once it is closed, the window will be authenticated accordingly ClientContext returned.

I tried with GetAppOnlyAuthenticatedContext. GetAzureADAppOnlyAuthenticatedContext and GetAzureADNativeApplicationAuthenticatedContext but none of them seemed to work.

UPDATE 2 – Since I still can not find a suitable solution and there GetWebLoginClientContext from SharePointPnPCoreOnline The package works well enough to solve my immediate problem. I simply chose this particular method and put it directly into my app (which eliminates the huge amount of dependency). For reference, this is the implementation of this method:

https://github.com/SharePoint/PnP-Sites-Core/blob/master/Core/OfficeDevPnP.Core/AuthenticationManager.cs#L322

I will continue to update this post if better solutions are available.

csom – Force the file naming convention in a folder in a document library SharePoint Online

SharePoint Online specific.

I wanted to know if it's possible to enforce filename conventions at the folder or subfolder level in a document library.

For example, I have a document library called "Documents" with many subfolders. I want to enforce a specific file naming convention for all Word (docx) files that are uploaded to a Legal folder, such as a folder. "Document_Name_Department_MMYYYY".

Then similar to another filename convention in the IT folder, and so on.

I've found a site that explains how to do this with the CSOM (https://www.tatvasoft.com.au/blog/how-to-implement-remote-event-receiver-in-sharepoint-online /).

Does anyone know if this is possible with JS, No-Code, Azure or Flow? Basically an alternative, instead of the CSOM example above.

Thank you so much!

Do not retrieve all FieldValues ​​in Powershell CSOM Sharepoint 2016

I've created a Powershell script to get details about the file / folder size of the Sharepoint site.

However, not all fieldValues ​​can be retrieved from listItems. I get values ​​for $ listItem.FieldValues ​​("FileRef"), $ listItem.FieldValues ​​("FileRef"), etc. while I have $ listItem.FieldValues ​​("File_x0020_Size") or $ listItem.FieldValues ("EncodedAbsUrl") try. I do not get anything. In CSOM we can insert required properties in .Load. They do not know how to do this in Powershell. Thanks in advance

Add-PSSnapin Microsoft.SharePoint.PowerShell -ErrorAction SilentlyContinue
Add-Type -Path "C:Program FilesCommon FilesMicrosoft SharedWeb Server 
Extensions16ISAPIMicrosoft.SharePoint.Client.dll"
Add-Type -Path "C:Program FilesCommon FilesMicrosoft SharedWeb Server 
Extensions16ISAPIMicrosoft.SharePoint.Client.Runtime.dll"

function retrieveListItems($_web)
{

try
{
    Write-host "Processing Web :"$_web.URL
    $listCollection=$_web.Lists;
    $ctx.Load($listCollection);
    $ctx.ExecuteQuery();


    foreach ($list in $listCollection)
    {
        $ctx.Load($list.RootFolder)
        $ctx.ExecuteQuery()
        $weburl= $ctx.Web.ServerRelativeUrl
        $listUrl =$("{0}{1}" -f $ctx.Web.Url.Replace($ctx.Web.ServerRelativeUrl,''), $list.RootFolder.ServerRelativeUrl)


       if($list.Hidden -ne "true" -and $list.IsCatalog -ne "true" -and  $list.BaseType -eq "DocumentLibrary")
       {          

            "{0}`t{1}`t{2}`t{3}`t{4}`t{5}`t{6}" -f $list.Title, $list.BaseType, $list.RootFolder.ServerRelativeUrl,$list.Title,"EnterSize", $list.LastItemModifiedDate, $list.ItemCount | Out-File -FilePath $outputFile -Append 
             Write-host $list.Title

            $listItems = $list.GetItems((Microsoft.SharePoint.Client.CamlQuery)::CreateAllItemsQuery())
            $ctx.Load($listItems);
            $ctx.ExecuteQuery();


            foreach($listItem in $listItems)
            {

               # $sizeMB = "{0:N2}" -f (($listitem("File_x0020_Size"))/1MB)  
                 #Here I am getting $sizeMB=0
               $length=$listItem.File.Length
                 #Here I am getting $length=0

               $sizeN=$listItem.FieldValues("File_x0020_Size")
                #Here I am getting $sizeN=0

               #check if ListItem is Folder or File
                if($listItem("FSObjType") -eq 1)
                {                    
                    "{0}`t{1}`t{2}`t{3}`t{4}`t{5}`t{6}" -f $listItem("FileLeafRef"),'Folder',$listItem("FileRef"),$list.Title,$sizeMB,$listItem("Modified"),$listItem("ItemChildCount") | Out-File -FilePath $outputFile -Append
                }
                else
                {
                    "{0}`t{1}`t{2}`t{3}`t{4}`t{5}`t{6}" -f $listItem("FileLeafRef"),'ListItem',$listItem("FileRef"),$list.Title,$sizeMB,$listItem("Modified"),$listItem("ItemChildCount") | Out-File -FilePath $outputFile -Append
                }
            }   

        }     
    }
    if($_web.Webs.Count -gt 0) 
    {
         foreach($subSite in $_web.Webs)
        { 

           $ctx.Load($subSite)
           $ctx.Load($subSite.Webs)
           $ctx.ExecuteQuery()

         $size = GetWebSize($subSite)  
         $sizeMB = "{0:N2}" -f (($size)/1MB)

           "{0}`t{1}`t{2}`t{3}`t{4}`t{5}`t{6}" -f $subSite.Title, 'Site', $subSite.ServerRelative,'',$sizeMB, $subSite.LastItemModifiedDate, $subSite.ItemCount | Out-File -FilePath $outputFile -Append 
           retrieveListItems($subSite) 
         }
     }
   $ctx.Dispose()
}
catch
{
    $_.Exception.Message
    $_ | Out-File -FilePath $logFile -Append
    exit
}

}


function GetWebSize ($web)      
{  
$ctx.Load($web.Folders) 
$ctx.ExecuteQuery() 
(long)$total = 0  
foreach ($folder in $web.Folders) {  
    $total += GetFolderSize -Folder $folder  
}          
return $total  
}  

function GetFolderSize ($folder)  
{  
$ctx.Load($folder.Files) 
$ctx.Load($folder.Folders) 
$ctx.ExecuteQuery(); 
(long)$folderSize = 0   
foreach ($file in $folder.Files) { 
    $folderSize += $file.Length;  
}  
foreach ($fd in $folder.Folders) {  
    $folderSize += GetFolderSize -Folder $fd  
}  
return $folderSize  
}  


function generateSiteDataReports
{
try
{

    $siteCollectionUrl= Read-Host -Prompt "Enter Site Collection URL"

    $Username =  Read-Host -Prompt "Enter userName: ";

    $password = Read-Host -Prompt "Enter password: " -AsSecureString ;        

    $logFile = "$PSScriptRootlog.txt"

    if(Test-Path $logFile)
    {
        Remove-Item $logFile
    }

    $outputFile = "$PSScriptRootSiteReport.csv"



    # Remove existing output file
    if(Test-Path $outputFile)
    {
         Remove-Item $outputFile
    }


    "{0}`t{1}`t{2}`t{3}`t{4}`t{5}`t{6}" -f "Title", "Object Type", "URL","ListName","Size", "Modified", "ItemCount" | Out-File -FilePath $outputFile -Append
    $ctx=New-Object Microsoft.SharePoint.Client.ClientContext($SiteCollectionUrl);
    $ctx.Credentials=New-Object System.Net.NetworkCredential($Username, $password);

    $ettkundWeb=$ctx.Web
    $ctx.Load($ettkundWeb)
    $ctx.Load($ettkundWeb.Webs)
    $ctx.ExecuteQuery()

    #Get Web Size
   # $size = GetWebSize($ettkundWeb)  
    $sizeMB = "{0:N2}" -f (($size)/1MB)  
   # $sizeGB = "{0:N2}" -f (($size)/1GB) 

    "{0}`t{1}`t{2}`t{3}`t{4}`t{5}`t{6}" -f $ettkundWeb.Title, 'Site', $ettkundWeb.ServerRelativeUrl,'',"Enter FileSize", $ettkundWeb.LastItemModifiedDate, $subSite.ItemCount | Out-File -FilePath $outputFile -Append 

    Write-host "Processing Web :"   $ettkundWeb.URL
    retrieveListItems($ettkundWeb)

}
catch
{
    $_.Exception.Message
    $_ | Out-File -FilePath $logFile -Append
    exit
}

}

generateSiteDataReports

csom – Authentication at Sharepoint Online stops working

I have a C # app with CSOM (latest version v16.1.19223.1200) and it worked fine until around mid-August 2019. I checked if the current password is still valid.

Code:

using (var context = new ClientContext(SharepointFolder))
{
    // Can't use current user, tried workaround linked from https://sharepoint.stackexchange.com/questions/176375/use-current-users-credentials-for-sharepoint-online-c

    var creds = System.IO.File.ReadAllLines(Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "creds.txt"));
    string userUpn = creds(0);
    // var spassword = new System.Net.NetworkCredential(userUpn, creds(1)).SecurePassword; // tried this as well
    var spassword = new SecureString();
    foreach (char c in creds(1)) { spassword.AppendChar(c); }
    context.Credentials = new SharePointOnlineCredentials(userUpn, spassword);

    Utils.Log.Info($"Getting page list from {context.Url}");

    var pagesList = context.Web.Lists.GetByTitle("Pages");
    context.Load(pagesList);
    context.ExecuteQuery();  ///// throws: Microsoft.SharePoint.Client.IdcrlException  HResult=0x80048821  Message=The sign-in name or password does not match one in the Microsoft account system.

    // ...
}

I have traced this with Fiddler and basically:

#   Result  Protocol Host                       URL
2   401     HTTPS   microsoft.sharepoint.com    /   <<<<<<<<<< Why not the path I provided in SharepointFolder?
3   502     HTTP    msoid.microsoft.com         /FPUrl.xml  
5   200     HTTPS   login.microsoftonline.com   /GetUserRealm.srf
7   200     HTTPS   msft.sts.microsoft.com      /adfs/services/trust/2005/usernamemixed
8   200     HTTPS   login.microsoftonline.com   /rst2.srf

Tracking Fiddler with browser access to the same address gives me first access SharepointFolder, is redirected for authentication and works fine.

How do I install the List View command-set extension in a site collection after deploying it with CSOM in an App Catalog?

I've created a Listview command extension with SPFX and added it to the App Catalog. Now I want to install this extension only for certain sites. I tried to add it as a custom action, but it does not work. Any help would be appreciated.

csom – Denied access to list after permissions have been granted to a group in a list

After giving View / Add / Edit / Open / Delete ListItems for a group in a list, the users of the group continue to be denied access when they try to access the list.
Here's the code I used to grant permissions:

var group = clientContext.Web.SiteGroups.GetById(id);   
 clientContext.Load(group);
 clientContext.ExecuteQuery();  

 BasePermissions permissions = new BasePermissions();
 permissions.Set(PermissionKind.ViewListItems); 
 permissions.Set(PermissionKind.AddListItems);
 permissions.Set(PermissionKind.EditListItems);
 permissions.Set(PermissionKind.OpenItems);
 permissions.Set(PermissionKind.DeleteListItems);


 RoleDefinitionCreationInformation rdcInfo = new 
 RoleDefinitionCreationInformation();
 rdcInfo.Name = "roleDefName";
 rdcInfo.Description = "Description";
 rdcInfo.BasePermissions = permissions;
 RoleDefinition roleDefinition = 
 clientContext.Site.RootWeb.RoleDefinitions.Add(rdcInfo);

 RoleDefinitionBindingCollection RoleDefinitionBindingColl = new 
 RoleDefinitionBindingCollection(clientContext);
 RoleDefinitionBindingColl.Add(roleDefinition);

 List targetList = web.Lists.GetByTitle(listTitle);
 targetList.BreakRoleInheritance(true, false);
 RoleAssignmentCollection collRoleAssign = targetList.RoleAssignments;
 RoleAssignment rollAssign = collRoleAssign.Add(group, 
 RoleDefinitionBindingColl);

 web.RoleAssignments.Add(group, RoleDefinitionBindingColl);
 web.Update();
 clientContext.ExecuteQuery();

Use PowerShell to connect to Project Online with CSOM under MFA

I am trying to interact with a PWA on a tenant for whom I have no choice but to use MFA. I'm trying to use the OfficeDev PnP library, which supports MFA, but can not use it for Project Online.

These works, but does not support MFA

$siteURL = "https://mytenant.sharepoint.com/sites/pwa"
$username = "my.name@mytenant.onmicrosoft.com"
$password = Read-Host -Prompt "Enter password" -AsSecureString
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($username, $password)
# Create & configure a client context connection
$pctx.Credentials = $credentials
# ...load stuff
$pctx.ExecuteQuery()

This uses Office Dev PnP to obtain an MFA-friendly authentication context it does not work (I get a 403 on the $pctx.ExecuteQuery())

$authmgr = new-object OfficeDevPnp.Core.AuthenticationManager
$pctx = New-Object Microsoft.ProjectServer.Client.ProjectContext($siteUrl)
$pctx.Credentials = $authmgr.GetWebLoginClientContext($siteURL).Credentials
# ...load stuff
$pctx.ExecuteQuery()

This latter method works well for a simple SharePoint Online ClientContext. Maybe that's the problem $authmgr.GetWebLoginClientContext($siteURL) returns a ClientContext, not a ProjectContext.

edits:

  • Try according to Gautam's suggestion $pctx = $authmgr.GetWebLoginClientContext($siteURL): This fails when running a query to load projects No overload was found for "Load" and the number of arguments: "1" Embassy. Here I believe that $ pctx does not know that it should be a ProjectContext, and that it is still a ClientContext (therefore, nothing has done the ProjectServer CSOM).

For completeness, here's the full code I've tried here:

# Load libraries
$PNPPath = "C:PathToPnP"
Add-Type –Path "$PNPPathMicrosoft.SharePoint.Client.dll"
Add-Type –Path "$PNPPathMicrosoft.SharePoint.Client.Runtime.dll"
Add-Type -Path "$PNPPathMicrosoft.ProjectServer.Client.dll"
Add-Type -Path "$PNPPathOfficeDevPnP.Core.dll"

# do stuff
$siteURL = "https://mytenant.sharepoint.com/sites/pwa"
$authmgr = New-Object OfficeDevPnp.Core.AuthenticationManager
$pctx = $authmgr.GetWebLoginClientContext($siteURL)    
$projects = $pctx.Projects
$pctx.Load($projects)
$pctx.ExecuteQuery()
  • I also tried to convert the ClientContext directly into a ProjectContext $pctx = (Microsoft.ProjectServer.Client.ProjectContext)$authmgr.GetWebLoginClientContext($siteURL) but this fails with a Can not convert … Error.

sharepoint online – Should I use Microsoft Graph or CSOM when integrating .NET in O365?

I have an existing integration based on CSOM that I need to switch from one .NET solution to another. I realized that Microsoft now has a Graph API. I've tried to research recommendations for using the Graph API or CSOM, but I have not found any documentation that I thought was sufficiently meaningful on this topic.

The use case retrieves calendar events from O365.

Should we choose to use the Microsoft Graph API or the CSOM NuGet package? Or is there another alternative that should be used for integration? I do not just want to use CSOM because we have it when it's considered a bit dated.

I'm inexperienced when it comes to integration with Sharepoint / O365.

csom – The object returned by the following call stack is null. ListItemAllFields AddWithOverwrite folder

I'm working on the migration tool with SharePoint CSOM from file system to sharepoint.
Everything worked fine, until now I have a new exception for some of the folders below.

The method can not be called or the property can not be retrieved from the null object. object
The value returned by the following call stack is null. ListItemAllFields
AddWithOverwrite Folders at
Microsoft.SharePoint.Client.ClientRequest.ProcessResponseStream (Stream
responseStream)
Microsoft.SharePoint.Client.ClientRequest.ProcessResponse ()

in the bottom line

CreatedFolder = ParentSPFolder.Folders.AddWithOverwrite(DestPath, true);

I have already read the questions below, but have not found my case.

The method can not be called or the property can not be retrieved from the null object. The object returned by the following call stack is null. "File " "

Server Exception: Method can not be called or property can not be obtained from null object. The object returned by the following call stack is null. "File " "

Can you please tell me what's wrong with the code?

Thank you.