Login Login
MORE

WIDGETS

Widgets

Wanted articles
Who is online?
Article tools

SharePoint

From Aino Wiki

Jump to: navigation, search

Se non espressamente indicato in questa raccolta di informazioni mi riferisco a SharePoint OnLine.

SPO, Introduzione

Si possono creare due tipologie di siti con SahrePoint OnLine (SPO) utilizzando i modelli preimpostati: sito di comunicazione (communication sites) e siti del team (team site).
SPO che è supportato nell'ambiente di Microsoft 365. Per poterci lavorare è necessario avere dei permessi adeguati quindi poter essere un Site Owner altrimenti occorre rivolgersi al "Site collection Administrator" o al dipartimento IT.
Poiché tutto lambiente è dedicato al Web sia lo sviluppo che la fruizione è effettuata mediante il Bowser, tra tutti è preferibile usare Microsoft EDGE. Per quanto riguarda la fruizione su smartphone (mobile envinonment), se si usa Android occorre usare l'App dedicata e nessun browser è supportato.

Experience

Con Microsoft SharePoint Server 2016 si introduce una nuova Experience, la Modern Experience che va ad aggiungersi alla Classic Experience:

  • La "Classic Experience" è l’interfaccia utente originale di SharePoint: consente una personalizzazione piuttosto spinta a patto di avere competenze da sviluppatore.
  • La "Modern” Experience", invece, è pensata per i dispositivi mobili ed è caratterizzata da un design più accattivante: consente una minima personalizzazione dell’aspetto grafico anche senza competenze da sviluppatore. Con la Modern Experience si son introdotte le tipologie di sito "Team site", "Communication site", "Hub sites".

Tipologie di sito

Team site

Destinati a facilitare la collaborazione tra utenti, si integra in particoalre con Microsoft Team e Exchenge (Outlook). Automaticamente viene creato un "Gruppo" (Microsoft 365 group) correlato, il sito è equipaggiato con una "Document library" ed un "Calendar".
In questa stesasa pagina c'è un esempio dic reazione di Un Team Site con annesso gruppo ed esempio di come rimuoverlo.
Un Team Site può esseer pubblico o privato a seconda della visibilità con cui è possibile accedervi, questo è impostabile all'atto della creazione quando si sceglie la "Privacy Settings" (si può modificare anche successivamente). Un sito private è accessibile solo dai propri membri altrimenti uno pubblico sarà visibile dall'intera organizzazione.

Communication site

Creato principalmente allo scopo di condividere informazioni, non è creato un gruppo automaticamente.

Hub site

Sono dei collanti tra siti SharePoint utilizzati appunto per organizzare i siti in SharePoint online. Consentono di collegare tra loro i siti. Sono creati da SharePoint Administrators per che richeidono un alto livello di autorizzazione. Sono caratterizzati da una Home Page con un extra spazio orizontale posto al primo rigo in alto sotto il banner pricnipale, questo spazio è usato per collegare i siti associati.

Le basi

Le liste

La lista di SharePoint (app Microsoft Lists) è l'oggetto alla base di tutti i contenuti di un sito, sono delle raccolte dati. Ci riferiamo alle liste rilasciate con la "modern experience" rilasciata da Microsoft nel 2016.
Con l'app delle liste si potrà:

  • Creare liste utili per la tua routine lavorativa.
  • Tenere traccia delle risorse e degli eventi aziendali. Es. per i task, si potrà organizzare e tracciare le informazioni interne, ti aiuterà a distribuire le attività da svolgere in elenchi intuitivi, intelligenti e flessibili.
  • Gestire l'inventario.
  • Integrare chat, gruppi e calendari.

(fonte qui)
Ci sono 4 visualizzazioni predefinite:

  • Griglia. Si compone di righe e colonne personalizzabili per permettere agli utenti di modificare in modo rapido e intuitivo tutte le informazioni inserite.
  • Elenco. Simile alla griglia, ma senza funzionalità di modifica.
  • Galleria. La scelta migliore per costruire liste che includono immagini.
  • Calendario. L'opzione giusta per mettere in evidenza date e scadenze.

Customize

E' possibile creare una lista importando una tabella Excel o viceversa esportare una tabella Excel verso un sito SharePoint online.

Collegamento dinamico con tabelle Excel

E' possibile collegare una tabella di un Foglio Excel con una Lista (che sarà read-only) su un sito SharePoint, basta aprire il foglio con Excel e esportarlo verso SahrePoint, il vantaggio è poter modificare il file Excel ed aggiornare dinamicamente la lista SharePoint e "fare Push per gli aggiornamenti" ogni volta che dall'Excel clicco sul pulsante "Refresh".

SharePoint online Lsta Excel dinamica 01.png

Design

E' possibile rendere maggiornemnte visibile una lista aggiungendola al menu verticale di sinistra "Quick launch", per far questo una via è cliccare sulla voce "Site contents" dall'icona dell'ingranaggio, poi sull'icona "Site Settings" quindi scegliere nell elenco il link "Site libraries and lists".

SharePoint online List Settings 01.png

quindi scegliere la lista il cui link va a sx:

SharePoint online List Settings 02.png
SharePoint online List Settings 03.png

Quindi cambare l'impostazione:

SharePoint online List Settings 04 Quick launch.png

Viste dinamiche

In alcune liste e tra i documenti può esser utile impostare delle viste ad hoc per visualizzare determinate informazioni, per filtrare, usare layout, dei documenti.
Ad esempio supponendo di inserire una vista generica che mostri i documenti (per le Libray) degli ultimi 5 giorni (vista dinamica basata sulla data).
Andare su "Library settings", andare in fondo alla pagina e cliccare su "Create view":

SharePoint online Library NewView 01.png

Si può scegliere un modello, è consigliabile scegliere "All Documents", in questo modo sarà presente ovunque:

SharePoint online Library NewView 02.png

Crearla:

SharePoint online Library NewView 03.png

Definire il filtro:

SharePoint online Library NewView 04.png

Ora sarà disponibile così:

SharePoint online Library NewView 05.png

Main features

Queste sono impostabili nelle "Library settings".

SharePoint online Library Settings 01.png
SharePoint online Library Settings 02.png
SharePoint online Library Settings 03.png

SharePoint online Library Settings 04.png

Versioning

Di default SharePoint gestisce il versioning di qualsiasi file caricato su. Serve a mantenere una storia dei cambiamenti intervenuti su documenti.

Approvazione contenuti

Anche detto "Content approval", che è una feature per cui nodifiche a determinati documenti richiedono delle approvazioni prima del definitivo rilascio.

Permessi

Creazione di un nuovo gruppo con autorizzazioni custom:

SharePoint online Site Permission 01.png
SharePoint online Site Permission 02.png

Quindi creiamo i gruppo:

SharePoint online Site Permission 03.png
SharePoint online Site Permission 04.png

Specifici permessi

E' utile assegnare specifici permessi, magari usando grant custom (gruppi di permessi), ad oggetti come Liste o apps.
Aprire la Lista o l'App, dopo aver creato il "guppo di permessi", dalla rotellina dei Settings, cliccare su "Library settings" (NOTA questa azione si applicherà all'oggetto sottostante).
Supponendo che l'oggetto si chiami "Budget and Proposals", cliccare su "Permissions for this document library":

SharePoint online Site Permission 05.png

quindi, per prima cosa toglieremo l'ereditarietà dei permessi (sempre per evitare eccezioni non volute) quindi rimuoviamo i gruppi di autorizzazioni non ad hoc.

SharePoint online Site Permission 06.png

Sharing

Per disabilitare la possibilità che anche i membri possano condividere dei contenuti ma per far sì che ci sia sempre una specifica richiesta ad un Owner specifico.
Andare nel menù avanzato dei permessi:

SharePoint online Site Permission 08.png

quindi

SharePoint online Site Permission 07.png

Le Apps

Le Apps creabili internamente al sito SharePoint sono delle funzionalità inpacchettate in un oggetto chiamato App che potrà essere fruito da Mobile o genericamente attraverso le Power Apps

Workflow

Tips

Design

Overview PageModel
Rinominare il "Titolo", aprire la pagina: https://xxxx.sharepoint.com/sites/_siteName_/_layouts/15/prjsetng.aspx

Varie info

Autorizzazioni

Ci sono diverse vie per autorizzare l'accesso a risorse di Sharepoint da applicazioni custom esterne.
Per la gestione della condivisione delle risorse (collegato a OneDrive) al livello di organizzazione aziendale leggere il seguente articolo: docs.microsoft.com.

Sharepoint App-only

Doc docs.microsoft.com
SharePoint App-Only è superato ma ancora molto rilevante. Questo modello funziona sia con SharePoint Online che SharePoint 2013/2016 on-premises ed è ideale per predisporre la migrazione di applicazioni dall'on-premises all'Online.
Andare dal proprio Tenant, sulla pagina:

es1.:
https://contoso.sharepoint.com/_layouts/15/appregnew.aspx
es.2:
https://myTenant.sharepoint.com/sites/GiuseppeAino/_layouts/15/appregnew.aspx
infine la pagina:
https://myTenant.sharepoint.com/sites/GiuseppeAino/_layouts/15/AppInv.aspx
Esempio di registrazione App vs SharePoint.png

Sicurezza

Aperture di rete

Pagina ufficiale Microsoft, Office 365 URLs and IP address ranges: SharePoint Online and OneDrive for Business.

SharePoint Online and OneDrive for Business
ID Category ER Addresses Ports
31 Optimize
Required
Yes <tenant>.sharepoint.com, <tenant>-my.sharepoint.com
13.107.136.0/22, 40.108.128.0/17, 52.104.0.0/14, 104.146.128.0/17, 150.171.40.0/22, 2620:1ec:8f8::/46, 2620:1ec:908::/46, 2a01:111:f402::/48
TCP: 443, 80
32 Default
Optional
Notes: OneDrive for Business: supportability, telemetry, APIs, and embedded email links
No *.log.optimizely.com, click.email.microsoftonline.com, ssw.live.com, storage.live.com TCP: 443
33 Default
Optional
Notes: SharePoint Hybrid Search - Endpoint to SearchContentService where the hybrid crawler feeds documents
No *.search.production.apac.trafficmanager.net, *.search.production.emea.trafficmanager.net, *.search.production.us.trafficmanager.net TCP: 443
35 Default
Required
No *.wns.windows.com, admin.onedrive.com, officeclient.microsoft.com TCP: 443, 80
36 Default
Required
No g.live.com, oneclient.sfx.ms TCP: 443, 80
37 Default
Required
No *.sharepointonline.com, cdn.sharepointonline.com, privatecdn.sharepointonline.com, publiccdn.sharepointonline.com, spoprod-a.akamaihd.net, static.sharepointonline.com TCP: 443, 80
38 Default
Optional
Notes: SharePoint Online: auxiliary URLs
No prod.msocdn.com, watson.telemetry.microsoft.com TCP: 443, 80
39 Default
Required
No *.svc.ms, <tenant>-files.sharepoint.com, <tenant>-myfiles.sharepoint.com TCP: 443, 80

Se non si riesce a sincronizzare OneDrive: come fare, mettere a disabilitato la seguente voce delle Policy del computer:
Computer Configuration > Windows Components > OneDrive > “Prevent the usage of OneDrive for file storage”

Etc (Office 365 Internet Zone Settings)

Articolo "copiato" da: tuomi.ca

This is a follow-up to my 2015 post about the recommended IE Internet Security Zone settings for maximum user authentication happiness.

On the post https://tuomi.ca/2014/06/23/overcoming-sticky-logouts-office-365-azure-windows-intune-web-browser/, I tried to rationalize IE security settings relating to Office 365.

Here’s a good explanation of why we should care, as quoted from the more recent MSFT post:
“Starting with Windows Vista , Internet Explorer has a new security zone protection feature, called protected mode, and that is set up by default for Internet, Intranet and Restricted Security zones.

Understanding and Working in Protected Mode Internet Explorer

The effect of the protected mode is that the sites in these zones will not have access to the folders available to other application (i.e. data available in other zones). This means the cookies available for one session for a site in a Protected mode zone will not be accessible to a site that resides in a separate zone (and the other way around), which will trigger behind the scene repeated authentication attempts.”

Net result: persistent login prompts, hair pulling, annoyances. The fix? Either manually or through group policy, apply the following settings to your Windows workstations:

Trusted Sites Zone:
https://*.microsoftonline.com
https://*.sharepoint.com
https://*.sharepointonline.com
https://*.outlook.com
https://*.lync.com
https://*.office365.com
https://*.office.com
https://*.microsoftstream.com
https://*.sway.com
https://*.powerapps.com
https://*.yammer.com

Intranet Zone:
*.microsoftonline.com
*.sharepoint.com
*.sharepointonline.com
*.outlook.com
*.lync.com
*.office365.com
*.office.com
*.microsoftstream.com
*.sway.com
*.powerapps.com


References:
https://blogs.technet.microsoft.com/victorbutuza/2016/06/20/o365-internet-explorer-protected-mode-and-security-zones/ – Latest new URL’s added e.g. PowerApps.com
https://support.microsoft.com/en-us/help/2507767/problems-when-signing-out-of-office-365–azure–or-intune-in-a-web-bro – Original official reference.

SPO, Creazione Sito

Su SharePoint Online è veramente banale creare un nuvo sito web. Creato un nuovo sito, si ha a disposizione uno spazio "Documenti" nel quale inserire cartelle e associare utenti e permessi. Creato un sito verrà creato un Gruppo e relativi Workspace.
Creato il sito si può usare la relativa cartella "Documents" in esso contenuta per condividere files ed eventualmente sincronizzarli sul computer come mostrato in un successivo paragrafo.

SharePoint new site 01.png

quindi:

SharePoint new site 02.png

fornire le info anagrafiche del sito:

SharePoint new site 03.png

ed infine:

SharePoint new site 04.png

Cancellazione Rinominazione

Poiché un Sito è associato ad un Gruppo, per queste operazioni o si dispone di permessi Amministrativi e si perfeziona l'operazione dal portale Azure oppure si opera sul Gruppo.
Pertanto lo scopo si può raggiungere rinominando o cancellando il gruppo associato, dopo pochi minuti l'operazione si riverbera verso tutte le risorse coinvolte tra cui il sito ed i Workspace. Questo si può fare ad esempio dall'Outlook on-line.

SharePoint operations on Group 01.png

Quindi si apre il seguente popup da cui si sceglie di cancellare o rinominare:

SharePoint operations on Group 02.png

Condivisione cartella

Lo scopo è condividere una cartella e relativi files\documenti contenuti, con membri dell'organizzazione e far sì che sia fisamente disponibile su fileSystem.
Sostanzialmente si deve procedere con la creazione di un Sito Web SharePoint (vedere paragrafo qui sotto) e successivamente, poiché una delle risorse è una cartella documenti, si sincronizzerà con una cartella fisica del Computer dove si vuole accedere via FileSystem.

SharePoint new site 05.png

Quindi procedere con la sincronizzazione

SharePoint new site 06.png

SharePoint on-premises

Come accedere al Workflow Nintex:

SP workflow 01.png

e

SP workflow 02.png

SharePoint Framework

SharePoint Online Client Components SDK (usato per abilitare lo sviluppo con SharePoint OnLine)
You can use the SharePoint client object model (CSOM =ClientSideObjectModel) to retrieve, update, and manage data in SharePoint.
SharePoint makes the CSOM available in several forms:

  • .NET Framework redistributable assemblies
  • .NET Standard redistributable assemblies
  • JavaScript library (JSOM)
  • REST/OData endpoints

Microsoft scrive: "It's recommended to use the CSOM for .NET Standard version for all your SharePoint Online CSOM developments". Ma occorre avere l'accesso al portale Azure per poter registrare l'applicazione questo dipende dal tenant in cui si opera. Questa strada l'ho scartata perché il mio tenant non mi da l'accesso pertanto uso: CSOM .NET Framework.

docs.microsoft.com

Esempio Copia files SharePoint vs FileSystem

Usando l'approccio con CSOM .NET Framework che è il più "comodo" non richiedendo autorizzazioni dal portale Azure, segue esempio di Applicazione in Windows Form (framework 4.5.2).
Attenzione, installare le librerie usando NuGet Microsoft.SherePoint.Client e Microsoft.SharePointOnline.CSOM.

NuGet MicrosoftSharePointClient.png

Supponendo di organizzare la solution in un progetto Desktop app in Windows Form e una libreria Helper di SharePoint Online.
Segue l'App.config in cui parametrizzare le informazioni opzionali:

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
  </startup>
  <appSettings>
    <add key="SPO_RootURL" value="https://pizza.sharepoint.com" />
    <add key="SPO_SiteName" value="SitoDiTest" />
    <add key="SPO_SiteLibrary" value="Documents" />
    <add key="SPO_Access_EmailUserName" value="giuseppe.aino@pizza.it" />
    <add key="SPO_Access_Password" value="???????" />
    <add key="ClientSettingsProvider.ServiceUri" value="" />
  </appSettings>
  <system.web>
    <membership defaultProvider="ClientAuthenticationMembershipProvider">
      <providers>
        <add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
      </providers>
    </membership>
    <roleManager defaultProvider="ClientRoleProvider" enabled="true">
      <providers>
        <add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
      </providers>
    </roleManager>
  </system.web>
</configuration>

Progetto Windows Form

using SP = Microsoft.SharePoint.Client;
using System;
using System.Security;
using System.Windows.Forms;
using System.IO;
using System.Configuration;
using VF_SPO_Library;
using VF_Common;
 
//DOC: https://docs.microsoft.com/en-us/sharepoint/dev/sp-add-ins/complete-basic-operations-using-sharepoint-client-library-code
//SPO_Helper
//VF_SPO_Library
 
namespace SPSynchro
{
    public partial class FrmMain : System.Windows.Forms.Form
    {
        #region Attributi privati
        private static string m_SPO_RootURL
        {
            get
            {
                return ConfigurationManager.AppSettings["SPO_RootURL"].ToString(); ;
            }
        }
        private static string m_SPO_SiteName
        {
            get
            {
                return ConfigurationManager.AppSettings["SPO_SiteName"].ToString(); ;
            }
        }
        private static string m_SPO_SiteLibrary
        {
            get
            {
                return ConfigurationManager.AppSettings["SPO_SiteLibrary"].ToString(); ;
            }
        }
        private static string m_SPO_Access_EmailUserName
        {
            get
            {
                return ConfigurationManager.AppSettings["SPO_Access_EmailUserName"].ToString(); ;
            }
        }
        private static string m_SPO_Access_Password
        {
            get
            {
                return ConfigurationManager.AppSettings["SPO_Access_Password"].ToString(); ;
            }
        }
        private const string c_AppVersion = "1.00";
        #endregion
 
        private SPO_Helper m_SPO;
 
        public FrmMain()
        {
            InitializeComponent();
        }
 
        #region UI Event Handler
        private void FrmMain_Load(object sender, EventArgs e)
        {
            try
            {
                Txt_SPSiteTenant.Text = m_SPO_RootURL;          // https://pizza.sharepoint.com
                Txt_SPSiteName.Text = m_SPO_SiteName;           // CC-CVReportingGateway
                Txt_SPFFolderLibrary.Text = m_SPO_SiteLibrary;  // ResourceExchange
 
                string mainURL = string.Format("{0}/sites/{1}", m_SPO_RootURL, m_SPO_SiteName);
                TxtUserName.Text = m_SPO_Access_EmailUserName;
                TxtPassword.Text = m_SPO_Access_Password;
 
                m_SPO = new SPO_Helper(mainURL, m_SPO_Access_EmailUserName
                                              , Security.ToSecureStr(m_SPO_Access_Password));
                RcTxtOutput.Text += string.Format("{0}\r\n", m_SPO.SharePointMessageOut);
            }
            catch (Exception ex)
            {
                RcTxtOutput.Text += string.Format("Error: {0}\r\n", ex.Message);
                MessageBox.Show(ex.Message, "Form Load Error"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
        private void BtnDownload_Click(object sender, EventArgs e)
        {
            string strMsgOutcome = string.Empty;
            try
            {
                string docLibrary = TxtSP_URL_FirstFolder.Text;   //es:   /sites/CC-CVReportingGateway/ResourceExchange
                string subFoldersCSV = TxtSPSubFolder.Text;
                string destFolderFS = TxtDestFileSystem.Text;   //es:   D:\Tmp\
 
                m_SPO.DownloadFilesFromSharePoint(docLibrary, subFoldersCSV, destFolderFS
                                                , out strMsgOutcome);
                RcTxtOutput.Text += strMsgOutcome;
            }
            catch (Exception ex)
            {
                RcTxtOutput.Text += string.Format("Error: {0}\r\n", ex.Message);
                MessageBox.Show(ex.Message, "Error"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
        private void BtnUpload_Click(object sender, EventArgs e)
        {
            string strMsgOutcome = string.Empty;
            try
            {
                string siteUrl = TxtMainURL.Text;                       //Es.: https://pizza.sharepoint.com/sites/CC-CVReportingGateway
                string docLibrary = Txt_SPFFolderLibrary.Text;          //FirstFolder
                string clientSubFolder = TxtSPSubFolder.Text;
                string fileNameLocalFullPath = TxtSrcFileSystem.Text; // D:\Tmp\Img\file.ext
 
                m_SPO.UploadFileToSharePoint(siteUrl, docLibrary, clientSubFolder
                                    , fileNameLocalFullPath, out strMsgOutcome);
 
                RcTxtOutput.Text += string.Format("File {0} caricato in: {1}\r\n{2}\r\n\r\n"
                                    , fileNameLocalFullPath, clientSubFolder, strMsgOutcome);
            }
            catch (Exception ex)
            {
                RcTxtOutput.Text += string.Format("Error: {0}\r\n", ex.Message);
                MessageBox.Show(ex.Message, "Error"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
 
        private void BtnDeleteSPOFile_Click(object sender, EventArgs e)
        {
            string strMsgOutcome = string.Empty;
            try
            {
                string docLibrary = TxtSP_URL_FirstFolder.Text;
                string subFoldersCSV = TxtSPSubFolder.Text;
                string fileName = TxtFileName.Text;
 
                if (m_SPO.DeleteFileFromSharePoint(docLibrary, subFoldersCSV, fileName
                                                , out strMsgOutcome))
                {
                    RcTxtOutput.Text += string.Format("CANCELLATO File {0} caricato in: {1}\r\n\r\n"
                                        , fileName, subFoldersCSV);
                }
                else
                {
                    RcTxtOutput.Text += string.Format("Cancellazione FALLITa o File {0} non trovato.\r\n\r\n"
                                        , fileName);
                }                
            }
            catch (Exception ex)
            {
                RcTxtOutput.Text += string.Format("Error: {0}\r\n", ex.Message);
                MessageBox.Show(ex.Message, "Error"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
        private void BtnCreateDirectory_Click(object sender, EventArgs e)
        {
            string strMsgOutcome = string.Empty;
            try
            {
                string docLibrary = Txt_SPFFolderLibrary.Text;
                string directoryName = TxtDirectoryToCreateOrRemove.Text;
                string execOutcome = m_SPO.CreateFolder(docLibrary, directoryName);
 
                RcTxtOutput.Text += string.Format("{0}\r\n\r\n", execOutcome);
            }
            catch (Exception ex)
            {
                RcTxtOutput.Text += string.Format("Error: {0}\r\n", ex.Message);
                MessageBox.Show(ex.Message, "Error"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
        private void BtnDeleteDirectory_Click(object sender, EventArgs e)
        {
            string strMsgOutcome = string.Empty;
            try
            {
                string targetFolderFullPath = string.Format("{0}/{1}", Txt_SPFFolderLibrary.Text, TxtDirectoryToCreateOrRemove.Text);
 
                string execOutcome = m_SPO.DeleteFolder(targetFolderFullPath);
                RcTxtOutput.Text += string.Format("{0}\r\n\r\n", execOutcome);
            }
            catch (Exception ex)
            {
                RcTxtOutput.Text += string.Format("Error: {0}\r\n", ex.Message);
                MessageBox.Show(ex.Message, "Error"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
        private void BtnRefresh_Click(object sender, EventArgs e)
        {
            string strMsgOutcome = string.Empty;
            try
            {
                strMsgOutcome = m_SPO.RefreshLogin();
                RcTxtOutput.Text += strMsgOutcome;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Error"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
        private void BtnSelectDestDownFolder_Click(object sender, EventArgs e)
        {
            try
            {
                FolderBrwDlg_Dest.SelectedPath = TxtDestFileSystem.Text;
                if (string.IsNullOrWhiteSpace(Path.GetDirectoryName(TxtDestFileSystem.Text.Trim())))
                {
                    FolderBrwDlg_Dest.SelectedPath = Path.GetDirectoryName(TxtDestFileSystem.Text.Trim());
                }
                DialogResult result = FolderBrwDlg_Dest.ShowDialog();
                TxtDestFileSystem.Text = FolderBrwDlg_Dest.SelectedPath + "\\";
            }
            catch (Exception ex)
            {
                RcTxtOutput.Text += string.Format("Error: {0}\r\n", ex.Message);
                MessageBox.Show(ex.Message, "Error"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
        private void BtnSelectSrcFile_Click(object sender, EventArgs e)
        {
            try
            {
                OpenFileDlg.InitialDirectory = @"D:\";
                OpenFileDlg.Title = "Select the file to upload to SharePoint online directory";
                //OpenFileDlg.DefaultExt = "txt";
                //OpenFileDlg.Filter = "txt files (*.txt)|*.txt|All files (*.*)|*.*"; 
                //OpenFileDlg.FilterIndex = 2;  
                //this.OpenFileDlg.Multiselect = true;
                OpenFileDlg.CheckFileExists = true;
                OpenFileDlg.CheckPathExists = true;
                if (OpenFileDlg.ShowDialog() == DialogResult.OK)
                {
                    TxtSrcFileSystem.Text = OpenFileDlg.FileName;
                }
            }
            catch (Exception ex)
            {
                RcTxtOutput.Text += string.Format("Error: {0}\r\n", ex.Message);
                MessageBox.Show(ex.Message, "Error"
                                , MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
 
        private void infoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            string strMsgOutput = string.Format("Ver: {0}\r\n\r\nSviluppatore: {1}\r\nE-mail: {2}\r\n\r\n{3}"
                                                , c_AppVersion
                                                , "Giuseppe AINO"
                                                , "giuseppe.aino@pizza.it"
                                                , "SPINDOX.it");
            MessageBox.Show(strMsgOutput, "About"
                        , MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        #endregion
 
        #region Private methods
 
        private void ComposeUIAccessInfo()
        {
            //Base URL:
            TxtMainURL.Text = string.Format("{0}/sites/{1}"
                , Txt_SPSiteTenant.Text 
                , Txt_SPSiteName.Text);
            //SP First folder:      /sites/CC-CVReportingGateway/ResourceExchange
            TxtSP_URL_FirstFolder.Text = string.Format("{0}/{1}"
                , TxtMainURL.Text.Replace(Txt_SPSiteTenant.Text, string.Empty)
                , Txt_SPFFolderLibrary.Text);
        }
        #endregion
 
    }
}

Libreria Helper di SharePoint online:

using SP = Microsoft.SharePoint.Client;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security;
using System.IO;
 
namespace VF_SPO_Library
{
    public class SPO_Helper
    {
        public SP.ClientContext Context;
        /// <summary>
        /// Messaggio di output della libreria disponibile solo per determinate operazioni.
        /// Utile per il Log e troubleshooting
        /// </summary>
        public string SharePointMessageOut = string.Empty;
 
        /// <summary>
        /// Es.: https:\\pizza.sharepoint.com/sites/NomeDelSito
        /// </summary>
        private string m_mainURL = string.Empty;
        /// <summary>
        /// e-mail a cui corrisponde la licenza Office 365 per l'accesso a SharePoint Online
        /// </summary>
        private string m_userName = string.Empty;
        /// <summary>
        /// Password di dominio criptata
        /// </summary>
        private SecureString m_password = new SecureString();
 
        public SPO_Helper()
        {
        }
 
        /// <summary>
        /// Oltre ad istanziare la classe istanzia il Contex che è l'oggetto chiave per ogni operazione su SharePoint Online.
        /// Restituisce un messaggio di welcome di inizializzazione.
        /// </summary>
        /// <param name="mainURL">Es.: https: pizza.sharepoint.com/sites/NomeDelSito</param>
        /// <param name="userName">e-mail a cui corrisponde la licenza Office 365 per l'accesso a SharePoint Online</param>
        /// <param name="password">Password di dominio criptata</param>
        public SPO_Helper(string mainURL, string userName, SecureString password)
        {
            SharePointMessageOut = RefreshLogin(mainURL, userName, password);
        }
 
        #region Public methods
        /// <summary>
        /// Riesegue il login "verboso" su SharePoint. Può essere usato per loggarsi su differente sito,
        /// memorizza la MainURL e le credenziali di riferimento in questa istanza di classe.
        /// </summary>
        /// <param name="mainURL">Es.: https: pizza.sharepoint.com/sites/NomeDelSito</param>
        /// <param name="userName">e-mail a cui corrisponde la licenza Office 365 per l'accesso a SharePoint Online</param>
        /// <param name="password">Password di dominio criptata</param>
        /// <returns>Messaggio di avvenuto accesso e descrizione del sito SharePoint</returns>
        public string RefreshLogin(string mainURL, string userName, SecureString password)
        {
            m_mainURL = mainURL;
            m_userName = userName;
            m_password = password;
 
            return RefreshLogin();
        }
 
        /// <summary>
        /// Riesegue il login con i dati di riferimento già memorizzate nelle variabili locali a questa istanza di classe.
        /// </summary>
        /// <returns>Messaggio di avvenuto accesso e descrizione del sito SharePoint</returns>
        public string RefreshLogin()
        {
            string welcomeMsgOut = string.Empty;
 
            Context = new SP.ClientContext(m_mainURL); // Es.: "https://pizza.sharepoint.com/sites/NomeSito"
            Context.Credentials = new SP.SharePointOnlineCredentials(m_userName, m_password);
 
            // The SharePoint web at the URL.
            SP.Web web = Context.Web;
            // We want to retrieve the web's properties.
            Context.Load(web);
            // Execute the query to the server.
            Context.ExecuteQuery();
 
            // Now, the web's properties are available and we could display
            // web properties, such as title.
            welcomeMsgOut = string.Format("{0}\r\n{1}\r\n\r\n", web.Title, web.Description);
 
            return welcomeMsgOut;
        }
 
        /// <summary>
        /// Scarica da SharePoint, l'intero contenuto (solo files) nella cartella "subFoldersCSV" (sottostante la "docLibraryPath") e li colloca nella cartella locale "localFolderDest".
        /// </summary>
        /// <param name="docLibraryPath">URL relativo della cartella\libreria del sito, es.: /sites/CC-CVReportingGateway/ResourceExchange</param>
        /// <param name="subFoldersCSV">Percorso cartella sottostrante la principale ovvero la "docLibraryPath". Il divisore delle cartelle in questa stringa può essere \ oppure /</param>
        /// <param name="localFolderDest">Percorso sul FileSystem locale, es.: D:\Tmp\Immagini</param>
        /// <param name="strMsgOutcome">Messaggio di log con l'esito dell'operazione</param>
        /// <returns>Indica se almeno un file è stato scaricato in locale</returns>
        public bool DownloadFilesFromSharePoint(string docLibraryPath, string subFoldersCSV
                                                , string localFolderDest
                                                , out string strMsgOutcome)
        {
            SP.FileCollection files = null;
            bool leafFolderFound = false;
            bool fileDownloaded = false;
            int i = 0;
            int n = 0;
            string strSubMsgOutcome = string.Empty;
 
            strMsgOutcome = string.Empty;
            if (!string.IsNullOrWhiteSpace(subFoldersCSV))
            {
                subFoldersCSV = subFoldersCSV.Replace('/', '\\');
 
                string[] arrFoldersToSelect = subFoldersCSV.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
                n = arrFoldersToSelect.Length;
                SP.FolderCollection folders = Context.Web.GetFolderByServerRelativeUrl(docLibraryPath).Folders;
                Context.Load(folders);
                Context.ExecuteQuery();
 
                //es    subFoldersCSV = "Files\DaLoredana\Old"
                foreach (string folderToSelect in arrFoldersToSelect)
                {
                    i++;
                    foreach (SP.Folder folder in folders)
                    {
                        if (folder.Name == folderToSelect)
                        {
                            if (i < n)
                            {
                                folders = folder.Folders;
                                Context.Load(folders);
                                Context.ExecuteQuery();
 
                                foreach (SP.Folder folder_deep in folders)
                                {
                                    strMsgOutcome += string.Format("SubFolder: {0}\r\n", folder_deep.Name);
                                }
                            }
                            else
                            {
                                files = folder.Files;
                                Context.Load(files);
                                Context.ExecuteQuery();
                                leafFolderFound = true;
                            }
                            break;
                        }
                    }
                }
            }
            else
            {
                files = Context.Web.GetFolderByServerRelativeUrl(docLibraryPath).Files;
 
                Context.Load(files);
                Context.ExecuteQuery();
                leafFolderFound = true;
            }
            if (leafFolderFound
                && files != null
                && files.Count > 0)
            {
                fileDownloaded = DownloadAllLeafFileList(files, localFolderDest, out strSubMsgOutcome);
            }
 
            strMsgOutcome += strSubMsgOutcome;
            Context.Dispose(); //???
            return fileDownloaded;
        }
 
        /// <summary>
        /// Fa upload di un file dal locale FileSystem collocandolo in una cartella su SharePointOnline. 
        /// La cartella può esser annidata ma sottostante la cartellaprincipale\libreria indicata.
        /// </summary>
        /// <param name="siteUrl">Es.: https://pizza.sharepoint.com/sites/NomeDelSito</param>
        /// <param name="docLibraryName">Nome libreria (Cartella principale) su SharePoint, es.: Documents</param>
        /// <param name="clientSubFolder">Percorso cartella sottostante la principale es.: SottoCartellaSP\SottoSottoCartellaSP</param>
        /// <param name="fileNameFullPath">Percorso completo FileSystem locale es.: C:\Sorgente\testupload.pdf</param>
        /// <param name="strMsgOutcome">Messaggio di log con l'esito dell'operazione</param>
        public void UploadFileToSharePoint(string siteUrl, string docLibraryName
                                            , string clientSubFolder
                                            , string fileNameLocalFullPath // D:\Tmp\Img\Barcellona_1920x364.jpg
                                            , out string strMsgOutcome)
        {
            strMsgOutcome = string.Empty;
            clientSubFolder = clientSubFolder.Replace('/', '\\');
            string[] arrSPOFolderName = clientSubFolder.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);  // Files\daUmberto\xLoredana
            int i = 0;
            int n = arrSPOFolderName.Length;
 
            #region Insert the data                
            SP.Web web = Context.Web;
 
            SP.FileCreationInformation newFile = new SP.FileCreationInformation();
            newFile.Overwrite = true;
            byte[] fileContent = System.IO.File.ReadAllBytes(fileNameLocalFullPath);
            newFile.ContentStream = new MemoryStream(fileContent);
            newFile.Url = Path.GetFileName(fileNameLocalFullPath); //Barcellona_1920x364.jpg
 
            SP.List DocLibrary = web.Lists.GetByTitle(docLibraryName); //Non sicuro che funzioni
 
            SP.Folder SPOFolder = null;
 
            foreach (string spoFolderName in arrSPOFolderName)
            {
                if (i == 0)
                {
                    SPOFolder = DocLibrary.RootFolder.Folders.GetByUrl(spoFolderName);
                    Context.Load(DocLibrary);
                }
                else
                {
                    SPOFolder = SPOFolder.Folders.GetByUrl(spoFolderName);
                }
                SPOFolder.Update();
                Context.ExecuteQuery();
                i++;
            }
            SP.File UploadFile = SPOFolder.Files.Add(newFile);
 
            Context.Load(UploadFile);
            Context.ExecuteQuery();
 
            strMsgOutcome += string.Format("The File has been uploaded"
                                + Environment.NewLine + "FileUrl -->" + siteUrl
                                + "/" + docLibraryName + "/"
                                + clientSubFolder + "/" + Path.GetFileName(fileNameLocalFullPath));
            #endregion
        }
 
        /// <summary>
        /// Cancella un file su SharePoint, il file può esser annidato in base al persorso indicato in "subFoldersCSV", percorso che parte sotto "docLibraryPath".
        /// </summary>
        /// <param name="docLibraryPath">URL relativo della cartella\libreria del sito, es.: /sites/CC-CVReportingGateway/ResourceExchange</param>
        /// <param name="subFoldersCSV">Percorso cartella sottostrante la principale ovvero la "docLibrary". Il divisore delle cartelle in questa stringa può essere \ oppure /</param>
        /// <param name="fileName">Nome del file da cancellare</param>
        /// <param name="strMsgOutcome">Messaggio di log con l'esito dell'operazione</param>
        /// <returns>Indica se il file esiste nel percorso indicato per la cancellazione</returns>
        public bool DeleteFileFromSharePoint(string docLibraryPath     //es:   /sites/CC-CVReportingGateway/ResourceExchange
                                            , string subFoldersCSV
                                            , string fileName
                                            , out string strMsgOutcome)
        {
            bool deleted = false;
            strMsgOutcome = string.Empty;
 
            subFoldersCSV = subFoldersCSV.Replace('\\', '/');
            // Es.: /sites/CC-CVReportingGateway/ResourceExchange/SubFolder1/SubFoldern/FileName.ext
            string relativeFilePath = string.Format("{0}/{1}/{2}", docLibraryPath, subFoldersCSV, fileName);
 
            SP.File file = null;
            if (FileExists(relativeFilePath, out file, out strMsgOutcome))
            {
                file.DeleteObject();
                Context.ExecuteQuery();
 
                deleted = !FileExists(relativeFilePath, out file, out strMsgOutcome);
                strMsgOutcome = string.Format("Conferma file '{0}' cancellato", fileName);
            }
            else
            {
                deleted = true;
                strMsgOutcome = string.Format("Il file '{0}' non era presente", fileName);
            }
            return deleted;
        }
 
        /// <summary>
        /// Crea una nuova cartella su SharePoint, in realtà crea tutte le cartelle del percorso se assenti.
        /// </summary>
        /// <param name="docLibraryName">Semplice nome della cartella\libreria del sito, es.: Documents</param>
        /// <param name="newFolderFullPath">Percorso cartella sottostrante la principale ovvero la "docLibraryName". Il divisore delle cartelle in questa stringa può essere \ oppure /</param>
        /// <returns>Messaggio di log con l'esito dell'operazione</returns>
        public string CreateFolder(string docLibraryName  
                                , string newFolderFullPath)
        {
            string logOut = string.Empty;
            /* https://sharepoint.stackexchange.com/questions/94820/c-csom-create-folders-in-lists-programmatically */
            string[] arrSPOFolderName = newFolderFullPath.Split(new char[] { '\\' }, StringSplitOptions.RemoveEmptyEntries);
            SP.List list = Context.Web.Lists.GetByTitle(docLibraryName);
            //list.EnableFolderCreation = true;
 
            SP.Folder myRemoteFolder = list.RootFolder;
 
            //Scansiona ogni directory del path in "newFolderFullPath", se la cartella non esiste la crea automaticamente
            foreach (string myFolder in arrSPOFolderName)
            {
                Context.Load(myRemoteFolder);
                myRemoteFolder.Folders.Add(myFolder);
                Context.ExecuteQuery();
 
                myRemoteFolder = Context.Web.GetFolderByServerRelativeUrl(myRemoteFolder.ServerRelativeUrl + "/" + myFolder);
            }
            logOut = string.Format("Folder path '{0}' correctly performed.", newFolderFullPath);
            return logOut;
        }
 
        /// <summary>
        /// Elimina la cartella foglia specificata nel percorso indicato. Elimina anche le sottocartelle anche se non vuote.
        /// </summary>
        /// <param name="targetFolderFullPath">Percorso completo compresa la prima cartella ovvero la libreria. Es.: Documents\Files\NuovaSub1\TargetFolder</param>
        /// <returns></returns>
        public string DeleteFolder(string targetFolderFullPath)
        {
            string logOut = string.Empty;
 
            targetFolderFullPath = targetFolderFullPath.Replace('\\', '/');
 
            // Enter server relative URL of the folder
            SP.Folder spTargetFolder = Context.Web.GetFolderByServerRelativeUrl(targetFolderFullPath);
 
            //La cartella foglia sarà cancellata anche nel caso contenga files o altre cartelle
            spTargetFolder.DeleteObject();
 
            Context.ExecuteQuery();
            logOut = string.Format("Folder path '{0}' correctly removed.", targetFolderFullPath);
            return logOut;
        }
 
        /// <summary>
        /// Risponde alla domanda se il file esiste nel percorso specificato.
        /// </summary>
        /// <param name="relativeFilePathURL">Es.: /sites/CC-CVReportingGateway/ResourceExchange/SubFolder1/SubFoldern/FileName.ext</param>
        /// <param name="file">Se il file esiste restituisce le info del file in formato SharePoint</param>
        /// <param name="strMsgOutcome">Messaggio di log con l'esito dell'operazione</param>
        /// <returns>Se il file esiste o meno</returns>
        public bool FileExists(string relativeFilePathURL
                                , out SP.File file
                                , out string strMsgOutcome)
        {
            strMsgOutcome = string.Empty;
            try
            {
                SP.Web web = Context.Web;
 
                file = web.GetFileByServerRelativeUrl(relativeFilePathURL);
                Context.Load(file);
                Context.ExecuteQuery();
                strMsgOutcome = string.Format("File '{0}' exists and supplied in output.", file.Name);
                return true;
            }
            catch (Microsoft.SharePoint.Client.ServerException ex)
            {
                if (ex.ServerErrorTypeName == "System.IO.FileNotFoundException")
                {
                    file = null;
                    strMsgOutcome = string.Format("File '{0}' not exists.", file.Name);
                    return false;
                }
                else
                    throw;
            }
        }
 
 
        /// <summary>
        /// 
        /// </summary>
        /// <param name="rootFolder"></param>
        /// <param name="strMsgOutcome">Messaggio di log con l'esito dell'operazione</param>
        public void GetTitleFolderLists(string rootFolder
                                        , out string strMsgOutcome)
        {
            strMsgOutcome = string.Empty;
            SP.Web web = Context.Web;
 
            // Assume the web has a list named "Announcements".
            SP.List foldersList = Context.Web.Lists.GetByTitle(rootFolder);
 
            // This creates a CamlQuery that has a RowLimit of 100, and also specifies Scope="RecursiveAll"
            // so that it grabs all list items, regardless of the folder they are in.
            SP.CamlQuery query = SP.CamlQuery.CreateAllItemsQuery(); //CreateAllItemsQuery(100)
            SP.ListItemCollection items = foldersList.GetItems(query);
 
            // Retrieve all items in the ListItemCollection from List.GetItems(Query).
            Context.Load(items);
            Context.ExecuteQuery();
            foreach (SP.ListItem listItem in items)
            {
                // We have all the list item data. For example, Title.
                strMsgOutcome += string.Format("{0}\r\n", listItem["Title"]);
            }
            strMsgOutcome += string.Format("finish\r\n");
        }
        #endregion
 
        #region Private methods
        /// <summary>
        /// Data una lista di files già determinata provvede ciclicamente a scaricarli localmente nella cartella del FileSystem specificata.
        /// </summary>
        /// <param name="files">Elenco SharePoint di files candidati</param>
        /// <param name="localFolderDest">Cartella del FileSystem locale</param>
        /// <param name="strMsgOutcome">Messaggio di log con l'esito dell'operazione</param>
        /// <returns>Indica se almeno un file della lista è stato scaricato localmente</returns>
        private bool DownloadAllLeafFileList(SP.FileCollection files, string localFolderDest
                                                , out string strMsgOutcome)
        {
            bool fileDownloaded = false;
            strMsgOutcome = string.Empty;
 
            //localFolderDest deve finire con   \       !
            foreach (SP.File file in files)
            {
                SP.FileInformation fileInfo = SP.File.OpenBinaryDirect(Context, file.ServerRelativeUrl);
                Context.ExecuteQuery();
 
                var filePath = localFolderDest + file.Name;
                using (var fileStream = new System.IO.FileStream(filePath, System.IO.FileMode.Create))
                {
                    fileInfo.Stream.CopyTo(fileStream);
                }
                fileDownloaded = true;
                strMsgOutcome += string.Format("Copyed: {0}\r\n", file.Name);
            }
            strMsgOutcome += string.Format("{0} files scaricati\r\n", files.Count);
            return fileDownloaded;
        }
        #endregion
    }
}

Mappa e Link


MS Power apps | Power Automate


C# | OAuth


Parole chiave:

Author