If you developed applications for Sharepoint Online using sandbox solutions or client object model you probably know that not all things which are possible to do with farm solutions are possible in the cloud world. In such cases we need to use compromises and workarounds, e.g. instead of fully automated processes write instructions for administrators for finishing installation process manually. In this article I will write about one creative way for avoiding limitations of sandbox solutions and client object model: WatiN web application testing and automation framework.
WatiN is open source project and it is free for using in your projects. Like many other good projects in .Net stack it was migrated from WatiR framework from Ruby world. It allows to simulate actions which administrator may do in the web browser via UI, e.g. open particular pages, type text into textboxes, check/uncheck checkboxes, click buttons and others. The idea of using it in Sharepoint came to me when I faced with one task for which didn’t find solution neither via sandbox code nor by client object model. Suppose that we have custom content type Project Meeting inherited from Document Set. As you probably know for such content types in Sharepoint there is special Document Set settings page accessible on content type details page:
On this page we may specify additional settings of the document set (technically document set is advanced folder. Internally it inherits OTB Folder content type and adds additional functionality):
- Allowed content types – list of available content types which can be added into document set;
- Default content – default content type shown first in New document button in the ribbon when user is inside document set. Also it is used when user clicks New document from the list view inside document set;
- Shared columns – columns of the current document set which will be automatically inherited to the documents inside this document set (if content types of these documents have the same columns);
- Welcome page columns – fields of the current document set’s content type which will be shown on the document set’s welcome page which is displayed when user clicks on the document set inside the list (this is one of the big differences between document set and folder: when user clicks on the folder regular list view is opened).
The page looks like this:
In our example we will use custom content type for document set Project Meeting which extends parent CT with the following fields:
- Meeting Name
- Meeting Date
Inside this document set we will allow to create only documents which have another custom content type Project Meeting Document which inherits OTB Document content type and among with other metadata also have Meeting Name and Meeting Date fields. As document set and document content types have the same common fields (Meeting Name/Date) we may inherit them from document set to documents.
From UI everything looks quite straightforward, problems begin when we will try to automate the configuration of document sets and do it e.g. during provisioning. If we will check codebehind of the mentioned Document Set settings page we will see that configuration is mostly done via DocumentSetTemplate class from Microsoft.Office.DocumentManagement assembly and its properties. Compilation of the same code won’t cause errors in sandbox code, but in runtime we will get exception that this assembly doesn’t allow partially trusted callers. In Sharepoint 2013 there is also client version of this assembly Microsoft.SharePoint.Client.DocumentManagement, but investigation shows that it is very limited: has 4 classes including DocumentSet which contains only method Create(). This is not enough for working with document set settings in Sharepoint Online programmatically. And this is where I thought about WatiN library (to be true my first thought was to simulate raw HTTP POST request programmatically, but after I checked in Fiddler that it uses content-disposition: form-data for multi-part files upload I quickly switched to less extreme approach).
One of the problem with sandbox solutions is that when you deactivate it Web-scoped features from this solution are automatically deactivated as well on all sub sites in the current site collection (see Reactivate Web-scoped features from PowerShell using client object model in Sharepoint Online). When you activate solution back you need to reactivate these features on sub sites and in mentioned article I showed how to do it. But sometimes it is not enough: related with document sets after reactivation of sandbox solution settings of custom document sets defined in this solution are reset to default. I.e. in our example they will look like this:
As you can see instead of custom allowed content type it uses OTB Document now and custom document set columns are not inherited anymore. Of course for solving this problem we may write instructions for administrators and rely on them that during each solution update they will change settings of all documents sets back to the correct values manually. But we may go by different way and even without having appropriate mechanisms in sandbox code and client object mode automate configuration of document sets by using WatiN.
Here is the working script written on C# with WatiN which makes the same actions which administrator need to do for configuring documents sets after solution update:
I added a lot of comments to the program so I think it is quite self explanatory. Notice the way how the program is running: separate thread is created with STA apartment state (lines 11-15). If you will run this automation code in primary app thread you will get the following error:
The CurrentThread needs to have it's ApartmentState set to ApartmentState.STA to be able to automate Internet Explorer.
Having this code you will just need to run it (it is also quite easy to call it from PowerShell) and see how things happen on opened IE window by themselves without your interaction. Looks very impressive.
And few words about Sharepoint Online case. As you probably know before to do something there you need to authenticate yourself on login page https://login.microsoftonline.com with nice picture:
It adds one additional step to our automation for authenticating ourselves:
As O365 login page uses HTML5 input element with type=”email” we need to use extended text field class for working with it in WatiN (natively it doesn’t support HTML5 fields). I found this trick on one of the StackOverflow discussions. Also we will use extension for simulating Enter key press on password textbox (WatiN don’t have native methods for that as well, or more correctly they don’t work like they work in original Ruby WatiR parent of WatiN). Here are all extensions needed for running this code:
With all of that you will be able to run your web automation code for configuring document set settings (or any other scenario) also in Sharepoint Online.
Even so there may be more correct ways to implement particular example used in this article in Sharepoint (while I didn’t find them), approach shown here is quite creative and may help you to automate very rich set of tasks and will make your set of Sharepoint experience wider.