Automated deployment for SharePoint Online can be one hell of a job. Apps and sandboxed solutions are the designated methods for provisioning, but are very limited. How about PowerShell? Yes! But not the default flimsy SPO cmdlets library. No, we are using SharePoint PowerShell, a third party PowerShell API for SharePoint (Online and On-premise).

SharePoint PowerShell

SharePoint PowerShell in fact a bunch of PowerShell Modules talking to CSOM, created by a guy called Jeffrey Paarhuis ūüôā ¬†Very usefull for Office 365 and private clouds where you don’t have access to the physical server.

What can you do with it?

  • Site Collection
    • Test connection
  • Site
    • Manage subsites
    • Manage permissions
  • Lists and Document Libraries
    • Create list and document library
    • Manage fields
    • Manage list and list item permissions
    • Upload files to document library (including folders)
    • Add items to a list with CSV
    • Add and remove list items
    • File check-in and check-out
  • Master pages
    • Set system master page
    • Set custom master page
  • Features
    • Activate features
  • Web Parts
    • Add Web Parts to page
  • Users and Groups
    • Set site permissions
    • Set list permissions
    • Set document permissions
    • Create SharePoint groups
    • Add users and groups to SharePoint groups
  • Solutions
    • Upload sandboxed solutions
    • Activate sandboxed solutions

And yet more to come…

How does it work? Well, like this:

# Include SPPS
Import-Module .\spps.psm1

# Setup SPPS
Initialize-SPPS -siteURL "https://example.sharepoint.com/" -online $true -username "[email protected]" -password "password"

# Activate Publishing Site Feature
Activate-Feature -featureId "f6924d36-2fa8-4f0b-b16d-06b7250180fa" -force $false -featureDefinitionScope "Site"

#Activate Publishing Web Feature
Activate-Feature -featureId "94c94ca6-b32f-4da9-a9e3-1f3d343d7ecb" -force $false -featureDefinitionScope "Web"

# Create a subsite
Add-Subsite -title "Subsite" -webTemplate "STS#0" -description "Description..." -url "subsite" -language 1033 -useSamePermissionsAsParentSite $true

# Create document library
Add-DocumentLibrary -listTitle "Testdoclib"

# Copy testfiles to this document library
Copy-Folder "C:\example\Testdoclib" "Testdoclib" $false

Try it yourself: example application 

And let me know what you think of it and how it can be improved!

The App Part in SharePoint 2013 is actually a Web Part version of an App. Like Web Parts in 2010 they reside in a small frame on the page. For the old Web Part this was some rendered ASPX, for an App Part this is an HTML-page in an IFrame.

In this post I want to explain, very shortly how to create an SharePoint-hosted App Part.

Build the App Part

I assume you have a developer site collection. If you haven’t yet, you can create one by selecting the¬†Developer Site¬†template under the¬†Collaboration¬†tab when creating a new site collection. This site collection has some build-in functionality that helps you deploy Apps from Visual Studio.

Ok, start off by creating a new SharePoint App in Visual Studio.  The App will be the container for the App Part.

Create an App with Visual Studio

In this scenario we are building a SharePoint-hosted App (Part) which means we can only use client-side code. If you want to know more about the different hosting options, please read this overview on MSDN.

Select App hosting options

Visual Studio creates an App with an hello-worldish script in the App.js. This script retrieves the display name of the current user and puts it in the <p id=”message”> on the default App page Default.aspx.

'use strict';

var context = SP.ClientContext.get_current();
var user = context.get_web().get_currentUser();

// This code runs when the DOM is ready and creates a context object which is needed to use the SharePoint object model
$(document).ready(function () {
 getUserName();
});

// This function prepares, loads, and then executes a SharePoint query to get the current users information
function getUserName() {
 context.load(user);
 context.executeQueryAsync(onGetUserNameSuccess, onGetUserNameFail);
}

// This function is executed if the above call is successful
// It replaces the contents of the 'message' element with the user name
function onGetUserNameSuccess()
 $('#message').text('Hello ' + user.get_title());
}

// This function is executed if the above call fails
function onGetUserNameFail(sender, args) {
 alert('Failed to get user name. Error:' + args.get_message());
}

You can run this app now and see that Visual Studio deploys the app to your developer site and starts debugging it.

Plain App

Did you know that you can debug your JavaScript straight in Visual Studio without the need of browser developer tools

We now add a Client Web Part item to the project. Despite of being called a Client Web Part, this will be the App Part.

Add Client Web Part

We want the wizard to create a new page for the App Part.

Create App Part page

This creates a Client Web Part and a page.

App Part Created

We can change the properties of the App Part, like the title, by modifying the Elements.xml.

When you open the App Part ASPX page you will notice that it looks different compared to the Default.aspx. Where the Default.aspx is using the SharePoint master page, the App Part Page is an empty page with no master page whatsoever. This is because the App Part Page will be shown in an IFrame, so we need an empty page. The only code Visual Studio generates out of the box are some JavaScript references and a script that will reference the right CSS.

<script type="text/javascript" src="../Scripts/jquery-1.7.1.min.js"></script>
<script type="text/javascript" src="/_layouts/15/MicrosoftAjax.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.runtime.js"></script>
<script type="text/javascript" src="/_layouts/15/sp.js"></script>

<script type="text/javascript">
 'use strict';

 // Set the style of the client web part page to be consistent with the host web.
 (function () {
  var hostUrl = '';
  if (document.URL.indexOf('?') != -1) {
   var params = document.URL.split('?')[1].split('&');
   for (var i = 0; i < params.length; i++) {
    var p = decodeURIComponent(params[i]);
    if (/^SPHostUrl=/i.test(p)) {
     hostUrl = p.split('=')[1];
     document.write('<link rel="stylesheet" href="' + hostUrl + '/_layouts/15/defaultcss.ashx" />');
     break;
    }
   }
  }
  if (hostUrl == '') {
   document.write('<link rel="stylesheet" href="/_layouts/15/1033/styles/themable/corev15.css" />');
  }
 })();
</script>

Now let’s create the same hello-worldish script on this page. Therefor we need the following script reference in the header:

<script type="text/javascript" src="../Scripts/App.js"></script>

And the following markup in the body:

<div>
 <p id="message">
  <!-- The following content will be replaced with the user name when you run the app - see App.js -->
  initializing...
 </p>
</div>

Run the App again, go to the developer site and add the App Part to the page.

Add App Part to page

Finally it would look something like this.

App Part on page

Happy coding!

Just for my reference, or anyone else interested, a link to the perfect guide on creating a custom filter section in the refinement panel.

http://www.domorewithsearch.com/customizing-the-refinement-panel-for-sharepoint-2010-search/

I created a List Event Receiver for my custom List Definition and wanted to set a view list properties programmatically in the EventReceiver. It worked perfectly in SharePoint 2010 but not in SharePoint Online.

To get the list I used the SPListEventProperties.List, but this object was causing some issues in SharePoint Online. I solved it by using the SPListEventProperties.Web.Lists[listname].

Code before:

SPList list = properties.List;

//enable content types
list.ContentTypesEnabled = true;

list.Update();

Code after:

SPList list = properties.List;
 SPWeb web = properties.Web;

// Re-opening the list, seems to be necessary because SharePoint Online has some sort of bug or timing issue.
 list = web.Lists[list.Title];

// enable content types
 list.ContentTypesEnabled = true;

list.Update();

This is a nasty SharePoint bug which caused some trouble in one of the SharePoint Online environments I was working on.

I created a Site Template using the “Save site as template” feature of SharePoint. Now when I created a new site from the template it resulted in the web parts all mixed up in the Left web part zone.¬†Remarkably¬†it was only the Left zone, the others were keeping their correct web part sequence.

When I took a look in the Onet.xml of the Site Template the web parts were nicely¬†divided¬†into seperate AllUsersWebPart’s and having correct WebPartZoneId’s. And¬†although¬†the web parts were also mixed up in the XML, the WebPartOrder properties were set correctly, 1 for the first, 2 for the second and so on. I still tried to¬†rearrange the¬†XML so the web parts would also have the right sequence in the syntax, but with no success, the web parts were still mixed up.

The final thing to do was to create a Web Part Zone for each Web Part. I did this by opening the page in SharePoint Designer and edit in the Advanced Mode (button on the ribbon).

This way the order is hardcoded on the page. I admit, it’s not very neat, but it does the trick.

In an¬†earlier post¬†I’ve explained that¬†it’s possible to use PowerShell for SharePoint Online. In this post I want to explain what the difficulties of SharePoint Online are and how we did manage to overcome that.

So, what’s the problem?

When you use the Client Object Model directly from PowerShell, it might seem to work, up to the point that you’re executing a query. Then you will receive a 403 – forbidden¬†error.

Off course, when you don’t provide any credentials you will not get access. You could try to provide a username, password and domain programmatically, but you won’t find any way to authenticate. This is because the authentication method of SharePoint Online differs from the ones that¬†Client Object Model supports.

What’s the solution?

The only thing we have to do is get an authenticated ClientContext and we’re ready to script. Fortunately, Microsoft has done all the hard work, because they have published a sample project for authentication with SharePoint Online.

We are going to pimp this project with our own code and make it possible to retrieve and use an authenticated ClientContext in PowerShell.

Go ahead, download¬†sample project¬†and open the ClaimsAuth solution file in Visual Studio. You will see that it also loads a project called¬†Sp_Ctx; you can remove or just ignore it, we won’t use it.

Now, in the ClaimsAuth project add a new class called “SPOContext” and use the following code:

using System.Net;
using Microsoft.SharePoint.Client;
using MSDN.Samples.ClaimsAuth;

public class SPOContext : ClientContext
{

  public SPOContext(string siteUrl) : base(siteUrl)
  {
    // this method gives a popup asking for credentials
    CookieCollection cookies = ClaimClientContext.GetAuthenticatedCookies(siteUrl, 0, 0);

    this.ExecutingWebRequest += delegate(object sender, WebRequestEventArgs e)
    {
      e.WebRequestExecutor.WebRequest.CookieContainer = new CookieContainer();
      foreach (Cookie cookie in cookies)
      {
        e.WebRequestExecutor.WebRequest.CookieContainer.Add(cookie);
      }
    };
  }

  // need a plain Load method here, the base method is some
  // kind of dynamic method which isn't supported in PowerShell.
  public void Load(ClientObject objectToLoad)
  {
    base.Load(objectToLoad);
  }
}

As you can see, we made an object that inherits from the ClientContext. The magic happens in the constructor; a pop-up will be shown where the user can login with his credentials. It then receives a few cookies which are stored and sent with each request. The cookies are the fairy dust in all of this, the cookies make it possible to authenticate with each request.

You also see a Load method. Why do we need this? The base class already has a Load method! Yes, but that method is some kind of dynamic method which isn’t supported in PowerShell. This custom Load method now acts as a wrapper for the real Load method.

This is it! Build the project and test the ClaimsAuth.dll according to my previous post.

I was fighting with this all day long.

I created a WCF service project (the host) and placed the ServiceContract (Interface) in a separate assembly. In another project (the consumer) I referenced that assembly and generated a proxy, with add service reference, and made sure the “reuse types in referenced assemblies” was checked. It then generated the proxy, but not using my handmade interface. To be entirely clear: it is generating an interface, but not using mine from the referenced assembly.

That’s weird, I thought I checked reuse types? So I tried it over and over with different settings, endpoints and cups of coffee, but with no success. So at the end of the day I googled a bit and found out that the “reuse types in referenced assemblies” only applies to DataContracts and not to ServiceContracts! Doh!

So, is it a bug or is it a feature? Well, to me it makes no sense that ServiceContracts don’t get reused, so in my opinion it’s a bug.

What are our options then? Not using the “add service reference”, but doing it manually with a few lines of code, which is also a bit neater:

// Supply the binding and address in code
Binding binding = new BasicHttpBinding();
EndpointAddress address = new EndpointAddress("http://tempuri.org/address");
IServiceContract channel = ChannelFactory.CreateChannel(binding, address);

// Or read them from the config file
ChannelFactory channelFactory = new ChannelFactory();
IServiceContract channel = channelFactory.CreateChannel();

I looked for hours! I can’t find this thing anywhere else on the internet! There must be a complete group of developers and designers that have been struggling with this before! I can’t believe I’m supposed to be the first one to put this solution on the world wide web.

All I wanted to do is to disable the wordwrap in a specific div in SharePoint, like so:

white-space: nowrap;

It worked perfectly in all browsers, except for… That’s right! Internet Explorer!

After struggling for half a day I finally found out that SharePoint inserts another piece of styling called word-wrap. This is the SharePoint code:

word-wrap: break-word;

All I had to do is override this in my own style and voila, it finally works!

And now the working style looks like this:

white-space: nowrap;word-wrap: normal;

My Story

By default, it’s only possible to sort on relevance and modified date in the Core Results Web Part. And it also¬†isn’t possible to give a sorting direction, it’s always descending.

Now a client wanted to show the last created discussions on¬†the homepage of it’s SharePoint, off course sorted by creation date. Out of the box this isn’t possible, but luckily somebody else had the same problem and came with a neat solution: http://www.insidesharepoint.net/post/2011/02/16/Creating-a-sortable-CoreResultsWebPart-in-SharePoint-2010.aspx

I played around a bit with that code, but couldn’t get it to work. The most common error I got was Property doesn’t exist or is used in a manner inconsistent with schema settings.

At this time of writing my expertise in the SharePoint Search maze isn’t that great, but I read something about a Managed Metadata Properties in the blog post. After playing around with custom managed properties for a while I finally got it to work. The trick is to create a custom Managed Property with mappings to, in my case, Basic:15;ows_start_x0020_Date,Office:12;creationdate and do a full crawl. Important! Do not do an incremental crawl! That will definitely not work! I cracked my head on that one already!

And then it works!

You could also forget the story above and follow the instructions beneath

These are the steps I took to work out my case, which is sorting Team Discussions by Creation Date.

First I created a scope named Discussions with a rule contentclass = STS_ListItem_DiscussionBoard.

Then I created a Managed Metadata Property named Created with a few mappings and settings like below.

Next thing to do is to start a full crawl. No incremental, that won’t work!

Now we can create our own Web Part. Create a new Visual Studio 2010 project, call it SortableCoreResultsWebPart. Add a reference to Microsoft.Office.Server.Search and add a new Web Part to the project, no Visual Web Part, just a regular. Name it SortableCoreResultsWebPart.

Open the SortableCoreResults.cs and overwrite the code with the following code.

    public class SortableCoreResultsWebPart : CoreResultsWebPart
    {
        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [WebDescription("Sort by this managed property")]
        [Category("MyProperties")]
        public string OrderByProperty { get; set; }

        [Personalizable(PersonalizationScope.Shared)]
        [WebBrowsable(true)]
        [WebDescription("Sort direction")]
        [Category("MyProperties")]
        public Microsoft.Office.Server.Search.Query.SortDirection SortDirection { get; set; }

        /// <summary>
        /// Override. First runs the base code, than collects the CoreResultsDatasource and
        /// sets the SortOrder property.
        /// </summary>
        protected override void ConfigureDataSourceProperties()
        {
            // only do stuff when search results are visible
            if (this.ShowSearchResults)
            {
                // run the base code
                base.ConfigureDataSourceProperties();
                try
                {
                    // if OrderByProperty is not set, use default behaviour
                    if (!string.IsNullOrEmpty(OrderByProperty))
                    {
                        // get the datasource and change the sortorder
                        CoreResultsDatasource dataSource = this.DataSource as CoreResultsDatasource;
                        dataSource.SortOrder.Clear();
                        dataSource.SortOrder.Add(OrderByProperty, SortDirection);
                    }
                }
                catch (Exception)
                {
                    // handle this error! and show a friendly error message
                }
            }
        }
    }

Don’t forget to add an using for Microsoft.Office.Server.Search.WebControls.

Run the thing and add the Web Part to the page. An error will pop up saying SrhdcNoKeywordException was unhandled, skip it by pressing F5 or clicking continue a couple of times.

Edit the Web Part, open the Location Properties and modify the scope to Discussions. Open Result Query Options and modify Fixed Keyword Query to contentclass:STS_ListItem_DiscussionBoard. Finally fill the OrderByProperty with Created and set a SortDirection.

 Save and refresh the page. Watch your web part sort like Dustin Hoffman in Rain Man!

For .NET

Resharper (free-to-try, ‚ā¨131)

Resharper is an extension for, in general,¬†intellisense. It’s very powerfull in different ways.¬†E.g. it checks your code for compiling issues on-the-fly and giving possible options to resolve it automatically.

download:
http://www.jetbrains.com/resharper/download/index.html

BugAid (free-to-try, $49)

BugAid is an extension for the variable watcher in debug-mode. Convince yourself with this video http://youtu.be/0GuAq76-D-s.

download:
http://www.bugaidsoftware.com/

For SharePoint

CKS: Development Tools Edition (free)

This project extends the Visual Studio 2010 SharePoint project system with advanced templates and tools.  Using these extensions you will be able to find relevant information from your SharePoint environments without leaving Visual Studio.

download:
http://cksdev.codeplex.com/

Visual Studio 2010 SharePoint Power Tools (free)

Also extends Visual Studio 2010 with templates and tools, especially focussed on sandboxed solutions.

download:
http://visualstudiogallery.msdn.microsoft.com/8e602a8c-6714-4549-9e95-f3700344b0d9