Link to home
Start Free TrialLog in
Avatar of Ama Olv
Ama Olv

asked on

Connect to SharePoint Online with CSOM, using user credentials

I am trying to get the following "SharePoint Hello Word" to work:

Sub Main()

    ServerUrl = "https://companyname.sharepoint.com/sites/TestingWeb"
    Using Context As New Client.ClientContext(ServerUrl)

            AddHandler Context.ExecutingWebRequest, AddressOf ExecutingWebRequest_Handler
            Context.AuthenticationMode = Client.ClientAuthenticationMode.Default
            Context.Credentials = System.Net.CredentialCache.DefaultCredentials

            Dim ThisWeb As Client.Web = Context.Web
            Context.Load(ThisWeb)

            Context.ExecuteQuery()
            MsgBox($"Web = {ThisWeb.Title}")

    End Using

End Sub

Private Shared Sub ExecutingWebRequest_Handler(sender As Object, e As Client.WebRequestEventArgs)
        Try
            e.WebRequestExecutor.WebRequest.Headers.Add("X-FORMS_BASED_AUTH_ACCEPTED", "f")
        Catch ex As Exception
            MsgBox("Could not append Web Request Header.", vbCritical Or vbOKOnly)
        End Try
End Sub

Open in new window


This code is executed from within a VSTO for Word or Excel, when the user opens a document from one of the SharePoint Document Libraires they have access to.
The end goal will be to perform basic (mostly readonly) operations on files and folders contained within that same Document Library the Word or Excel file was open from.

Since the user needs to be logged in to SharePoint to access the file in the first place, I would like to avoid using Context.Credentials = New SharePointOnlineCredentials(email, password).

When I execute the above code, I get a 401 Unauthorized error. What am I doing wrong?
Avatar of Zvonko
Zvonko
Flag of North Macedonia image

Everything fine in your code.

Except this line:

Context.AuthenticationMode = Client.ClientAuthenticationMode.Default

Open in new window


I do not need it in my code and get the Web.Title





Avatar of Ama Olv
Ama Olv

ASKER

Interesting... Are you sure the SharePoint site you tried did actually require credentials? Could it be that my ServerUrl value is wrong?
Did you execute the code from within a VSTO?

The way I run my tests: I have the mentioned code snippet executed from a button in an Add-In Ribbon of Word.
From Word, I open a document contained within the SharePoint site I want to test, then I click the button.

Sorry, I have not tested your code.The remote access to my company is currently not available.


I and I have not noticed that you handle the web access yourself.


Can you contact me on my email address in my profile?




I have tested your code as standalone EXE.

My compile line looks like this:


"C:\Windows\Microsoft.NET\Framework64\v4.0.30319\vbc.exe" /debug /target:exe /r:Microsoft.SharePoint.Client.dll /r:Microsoft.SharePoint.Client.Runtime.dll %*


And this is your code:

Imports System 
Imports System.Net 
Imports Microsoft.SharePoint 
Imports Microsoft.SharePoint.Client 
Public Module Hello	 
	Sub Main() 
		Dim ServerUrl as String = "https://workspace2.energy.mycompany.com/content/00109/" 
		Using Context As New Client.ClientContext(ServerUrl) 
			'//**Removed** AddHandler Context.ExecutingWebRequest, AddressOf ExecutingWebRequest_Handler 
			Context.AuthenticationMode = Client.ClientAuthenticationMode.Default 
			Context.Credentials = System.Net.CredentialCache.DefaultCredentials 
			Dim ThisWeb As Client.Web = Context.Web 
			Context.Load(ThisWeb) 
			Context.ExecuteQuery() 
			MsgBox("Web = " & ThisWeb.Title) 
		End Using 
	End Sub 
End Module

Open in new window


One more note.

If you do not provide userid and password but use:

System.Net.CredentialCache.DefaultCredentials

then you use some complex handshake process that transfers your Windows userid token to webserver.

Therefore is a good test to check browser connection to the SharePoint site before testing VSTO connect.

If browser connect fails for any reason then for sure VB connect will not work.

On other hand I have had also the situation where scripting connection only worked after browser connection was opened in beforehand, for example for WebDAV. You guess what my sollution was after that observation? Open and close browser in script :  )


 


Avatar of Ama Olv

ASKER

I guess the problem might be with VSTO wrapping the calls made by the add-in DLL.
I'll run some tests via a Console project and see if it works.

Do you think I might have better chances if using the SharePoint REST API instead?
At the moment all I need is to be able to list or rename the files located in the same folder as the word document the VSTO executes from.
I use System.IO.DirectoryInfo when the document is on a local folder.

The test for  Context.Web.Title is a good test for correct access priviledges.

Therefore use your VB snippet in command line EXE format compiled as I have show you.

If that works, then you can expand that smal script for using System.IO.Directory and System.IO.File to rename or delete the SharePoint files with their WebDAV paths. For the the WrbDAV path open the Document Library in Internet explorer and the select in Ribbon for library the Explorer button.

I have done that in different tools for my department SharePoint.

     

Shell I show you how I handle our SharePoint files in a  VB EXE?


Here the Directory and Files version:

Imports System 
Imports System.IO 
Imports System.Net 
Imports Microsoft.SharePoint 
Imports Microsoft.SharePoint.Client 
Public Module Hello	 
	Sub Main() 
		Dim ServerUrl as String = "https://workspace2.energy.siemens.com/content/00109/" 
		Dim strFolderPath as String = "\\workspace2.energy.siemens.com\content\00109\SiteAssets\Tools\" 
		Dim strOldFileName as String = "CreateRepositoryFolders.aspx" 
		Dim strNewFileName as String = "CreateRepositoryFolders_v01.aspx"		 
		Using Context As New Client.ClientContext(ServerUrl) 
			'//**Removed** AddHandler Context.ExecutingWebRequest, AddressOf ExecutingWebRequest_Handler 
			Context.AuthenticationMode = Client.ClientAuthenticationMode.Default 
			Context.Credentials = System.Net.CredentialCache.DefaultCredentials 
			Dim ThisWeb As Client.Web = Context.Web 
			Context.Load(ThisWeb) 
			Context.ExecuteQuery() 
			Console.WriteLine(vbCrLf & "Context.Web.Title: " & ThisWeb.Title) 
			Dim arrFolders(  ) As String 
			arrFolders = Directory.GetDirectories(strFolderPath) 
			Console.WriteLine(vbCrLf & "Folders:") 
			For i = 0 To UBound(arrFolders) 
				Console.WriteLine(arrFolders(i)) 
			Next 
			Try 
				Console.WriteLine(vbCrLf & "Renameing file {0} > {1}", strOldFileName, strNewFileName) 
				System.IO.File.Move(strFolderPath+strOldFileName, strFolderPath+strNewFileName) 
				Console.WriteLine("File renamed: " & strNewFileName) 
			Catch ex As Exception 
				Console.WriteLine(vbCrLf & "Can't rename file:" & vbCrLf & ex.Message) 
			End Try 
			Console.WriteLine(vbCrLf & "Files:") 
			Dim di As New IO.DirectoryInfo(strFolderPath) 
			Dim arFi As IO.FileInfo() = di.GetFiles("*") 
			Dim fi As IO.FileInfo 
			For Each fi In arFi 
				Console.WriteLine(fi.FullName) 
			Next 
		End Using 
	End Sub 
End Module

Open in new window

Avatar of Ama Olv

ASKER

Thank you once again for your help!
Directory.GetDirectories(strFolderPath) looks good. I'll give it s try tomorrow.

At the moment I am blocked because Application.ActiveDocument.Name returns the Https path to SharePoint, not the local OneDrive equivalent. If I was able to get the local path then I would not even need to work through SharePoint.

I'll Keep you posted
ASKER CERTIFIED SOLUTION
Avatar of Ama Olv
Ama Olv

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial