Sunday, March 29, 2015

Deploy JavaScript to SharePoint Online with a Console App


One of the new challenges facing SharePoint professionals is adding JavaScript files to SharePoint online. The most direct and simple approach that I have found is to use the UserCustomAction class to add a ScriptLink. To make the deployment a snap, use the SharePointOnlineCredentials class within a console application. The SharePointOnlineCredentials class allows you to access the site using your credentials. You will need full control permission to run this solution.

WARNING, improper use use of a UserCusomAction to add a ScriptLink WILL break your site/site collection in a very disturbing fashion. SharePoint will gladly serve you an absolutely blank page with no error. Therefore, it is recommended to test this solution prior to a production deployment.

Create a new Console App


Add references to SharePoint

Microsoft.SharePoint.Client
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.dll

Microsoft.SharePoint.Client.Runtime
C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\15\ISAPI\Microsoft.SharePoint.Client.Runtime.dll

Use SharePointOnlineCredentials

First, collect the url, logon and user password from the console. Create a new client context and set the credentials of the context to a new SharePointOnlineCredentials class.

static void Main(string[] args)
{

     Console.WriteLine("Enter SharePoint online url:");
     string url = Console.ReadLine();

     Console.WriteLine("Enter SharePoint online Login : ");
     string logon = Console.ReadLine();

     Console.WriteLine("Enter your password.");
     SecureString password = GetPasswordFromConsoleInput();

     using (var context = new ClientContext(url))
     {
           context.Credentials = new SharePointOnlineCredentials(logon, password);
     }

     Console.WriteLine("Press Enter to End");
     Console.ReadLine();
}


private static SecureString GetPasswordFromConsoleInput()
{
     ConsoleKeyInfo info;

     //Get the user's password as a SecureString
     SecureString securePassword = new SecureString();
     do
     {
         info = Console.ReadKey(true);
         if (info.Key != ConsoleKey.Enter)
         {
              securePassword.AppendChar(info.KeyChar);
         }
     }
     while (info.Key != ConsoleKey.Enter);
         return securePassword;
}

Use the Utility Functions

The downloadable code has a few functions built to list, add and remove ScriptLinks. I would start by just listing them out. The functions are executed directly after SharePointOnlineCredentials. 

/// <summary>
/// adds a scriptlink to the site 
/// </summary>
/// <param name="ctx"></param>
/// <param name="file"></param>
/// <param name="seq"></param>
private static void AddScriptLink(ClientContext ctx, string file, int seq)
{
// Register Custom Action
     var customAction = ctx.Site.UserCustomActions.Add();
     customAction.Location = "ScriptLink";
     customAction.ScriptSrc = file;
     customAction.Sequence = seq;
     customAction.Update();
     ctx.ExecuteQuery();

     Console.WriteLine("ScriptLink Added : {0}", file);
}
        
/// <summary>
/// remove all customactions from the site
/// </summary>
/// <param name="ctx"></param>
private static void ClearAllScriptLinks(ClientContext ctx)
{
     var customActions = ctx.Site.UserCustomActions;
     ctx.Load(customActions);
     ctx.ExecuteQuery();
     customActions.Clear();
     ctx.ExecuteQuery();

     Console.WriteLine("All SriptLinks removed");
}

/// <summary>
/// list the scriptlinks on the site
/// </summary>
/// <param name="ctx"></param>
private static void ListScriptLinks(ClientContext ctx)
{
     var customActions = ctx.Site.UserCustomActions;
     ctx.Load(customActions);
     ctx.ExecuteQuery();
            
     foreach(UserCustomAction ua in customActions)
     {
         if (string.Compare(ua.Location, "ScriptLink", true) == 0)
         {
              Console.WriteLine("Script Source : {0}, Sequence : {1}", ua.ScriptSrc, ua.Sequence);
         }
     }

     if(customActions.Count == 0)
     {
         Console.WriteLine("No ScriptLinks found for {0}", ctx.Url);
     }
}
 

/// <summary>
/// remove a scriptlink matching script source
/// </summary>
/// <param name="ctx"></param>
private static void RemoveScriptLink(ClientContext ctx, string scriptsource)
{
      var customActions = ctx.Site.UserCustomActions;
      ctx.Load(customActions);
      ctx.ExecuteQuery();

      foreach (UserCustomAction ua in customActions)
      {
          if (string.Compare(ua.ScriptSrc, scriptsource, true) == 0)
          {
               Console.WriteLine("Removing Script Src : {0}, Sequence : {1}", ua.ScriptSrc, ua.Sequence);
               ua.DeleteObject();
          }
      }

      if(ctx.HasPendingRequest)
      {
         ctx.ExecuteQuery();
      }
}

Download Source Code

https://github.com/spkrby/SriptLinkUtil

References


http://blogs.msdn.com/b/kaevans/archive/2014/02/23/call-o365-using-csom-with-a-console-application.aspx
http://blog.mastykarz.nl/deploying-custom-actions-app-model/
http://www.ashokraja.me/post/Refer-Scripts-and-CSS-Style-Sheet-in-SharePoint-2013-Visual-Web-Part-and-Master-Page.aspx