Thursday, December 17, 2015

People Picker MVC Sample


OfficeDev PnP has a great sample for using the people picker in a provider hosted add-in. The only problem is that the sample uses web forms. In this post I'll demonstrate using the people picker in an MVC application.

Create a new App for SharePoint

Make it Provider hosted
Choose MVC Web Application
Choose Windows Azure Access Control Service

Add a dummy module to the SharePoint project

Right click the SharePoint project and add a dummy module. This will allow you to easily get a SharePoint context.

Edit _Layout.cshtml 

Add MicrosoftAjax.js and a Styles section. Remove the menu and footer.


Copy files from the PnP Project Scripts folder into the MVC Scripts folder

app.js
peoplepickercontrol.js
peoplepickercontrol_resources.en.js

Copy files from the PnP Project Styles folder into the MVC Content folder

peoplepickercontrol.css

Edit the app.js file

Add functions for the chrome control, renderSPChrome and chromeLoaded.


Add a people picker to index.cshtml




Lets walk through this.

Line 1 add the CSS for the control.

Line 5 this is for loading the SharePoint chrome control. If this is not what you want you will need to include the SharePoint core.css file into your project or at least those bits needed for the people picker.

Lines 9 - 19 this is the html needed for the people picker. The ids are important. They are used by the JavaScript to build the control.

Line 29 add the people picker JavaScript files to the page


That's it. If you've followed along the people picker should be up and running in your MVC application. Full source code can be found here https://github.com/spkrby/MVCPeoplePicker.git











Wednesday, April 1, 2015

Use Powershell with SharePoint Online

Install Powershell on your machine

http://www.microsoft.com/en-us/download/details.aspx?id=40855

Install SharePoint Online Management Shell

http://www.microsoft.com/en-us/download/details.aspx?id=35588

Connect to SharePoint


Connect-SPOService -Url https://???????-admin.sharepoint.com -C
redential ?????@?????.onmicrosoft.com

I can't connect, I get the following error: "Current site is not a tenant administration site."
Fix: You must connect to the administration site. You're administration site will be something like this https://achme-admin.sharepoint.com


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




Sunday, February 27, 2011

Create Site Collections from Custom Site Templates

In SharePoint 2010 creating templates from sites is as simple as a few clicks. Using that template to create new site collections is a bit more involved. The standard approach goes something like this; download the newly created template, in central administration create a new site collection without specifying a template, navigate to the new site collection, when prompted for the site template upload your custom template. The problem with this approach it's too repetitive if you're going to create a lot of sites and site collections.

What I wanted to do was to select the template to create new sites and site collection just like the builtin ones. To do this you need to understand what's going on when you create a site template from the SharePoint interface. It's a solution file so we can rename it to a .cab file and take a look inside. Along with the manifest.xml file, there are folders for; ListInstances, Modules, PropertyBags, and WebTemplate. The webtemplate folder is the giveaway, what has been created for us is a definition for a webtemplate. The webtemplate folder contains a feature with a scope of "Site" that needs to be changed to a scope of "Farm".
That's it, this webtemplate can now be used to create site collections from central administration, after installation of coarse.



The steps; create the template, download the template, rename the template to .cab, extract the .cab file to a folder, modify the feature xml, convert folder back to .cab, rename to .wsp, add and deploy the solution. To convert the folder back to a cab file I used TUGZip.

Thursday, February 24, 2011

Disable ASP:Button onclick

A common requirement is to disable a button after it's been clicked. It can be accomplished by modifying two properties of the asp:button control. First, set the UseSubmitButton to "false". Second, modify the OnClientClick property to include "this.disabled=true;". These two settings will work in most cases. A problem will crop up if client side data validation is being used. The button will remain disabled and the user will not be able to click the button again. If you're using .Net validation controls you will need to check Page_ClientValidate() and then disable the button. 


<script type='text/javascript'>
   function disableBtn(control) {
     if (typeof Page_ClientValidate == 'function') {
        if (Page_ClientValidate()) { control.disabled = true; }
     }
     else
     { control.disabled = true; }
   }
</script>

<asp:Button runat="server" ID="btnSubmit" OnClientClick="disableBtn(this);" UseSubmitBehavior="false" OnClick="btnSubmit_Click" Text="Submit" />



Tuesday, December 28, 2010

SharePoint People Picker Limit Selection

By default, the people picker will let a user select anyone visible to the picker. This is not always an ideal situation. Luckily, there are a couple of ways to easily limit what the user can select from.

First, if you need to limit selection to site collection users, you can use an stsadm command

stsadm -o setproperty –url http://sitecollectionURL
       –pn peoplepicker-onlysearchwithinsitecollection –pv yes


There are a couple of other options to limit selection that involve setup in active directory. They can be found here; Keep it Simple!
Peoplepicker: Stsadm properties


Second, customize the people editor control with the SharePointGroup property. I've found this solution very helpful in customizing input screens as it gives really fine grained control over an individual field. The field below will only allow selection from "SomeGroup".

<SharePoint:PeopleEditor ID="plpEdit" runat="server" SharePointGroup="SomeGroup" />

Sunday, December 26, 2010

SharePoint People Picker Multiple Domains

The people picker is an important part of a SharePoint farm. Making sure that the correct users are available for selection is key. Issues almost always show up in farms where multiple domains need to be available for selection. The fix is a couple of stsadm commands, these commands work in SharePoint 2007 and 2010. 

By default, the application pool identity is used to search active directory. If the account does not have the correct permissions, you will need to encrypt the password for the account that will be used to search that domain. This account needs to be noted for password changes!

Set the encryption key (run on each WFE)
stsadm -o setapppassword -password  *********
Set the domains that should be searched  (run on one WFE per web application)
stsadm -o setproperty -pn peoplepicker-searchadforests 
       -pv domain:domain1;domain:domain2,domain2\account,password 
       -url http://webapp
A more detailed discussion can be found here:
http://blogs.msdn.com/b/joelo/archive/2007/03/08/cross-forest-multi-forest-configuration-additional-info.aspx