Error: Cannot add the specified assembly to the global assembly cache: [assemblyname.dll]

When you try to deploy and got the error “Cannot add the specified assembly to the global assembly cache: [assemblyname.dll]”, it looks like some process is lock your dll in the GAC. You need to kill that process. You can use the free Microsoft tool “Process Explorer”. Search your dll in this tool and kill the process. When you see the process “Microsoft.Alm.Shared.Remoting.RemoteContainer.dll” it is the Visual Studio Code Lens. You can turn it off as follow:

Tools -> Options -> Text Editor -> All Languages -> CodeLens

Templates, designs

Check if the current user is the search crawler

// check if the current user is the search crawler

var isMSSearch = !string.IsNullOrEmpty(Page.Request.UserAgent) && Page.Request.UserAgent.ToUpper().Contains(“MS SEARCH”);

isMSSearch = isMSSearch || Page.Request.QueryString.AllKeys.Contains(“ismssearch”); //workaround om als dev te zien wat search te als content krijgt

// skip if it is the search crawler

if (!isMSSearch)


// do some logic, current user is not the search crawler


Attach to ‘SharePoint solution with Debugger.Launch();

when you try to debug code in a SharePoint solution, you can do it as follow:


Add this line of code somewhere where you would like to debug:


Build the solution. Add the dll to the gac. Than start again a deployment of the solution.

Set/get Cache object

public static bool IsMailServiceAvailable()


bool? result = null;

// If not, try to get it from the cache.

result = HttpRuntime.Cache.Get(BwMailServiceAvailableKey) as bool?;

if (result == null)


// Nothing in the cache, get a lock on an object to make sure we’re the only one running this part of the code.

lock (lockHandleMailServiceAvailable)


// Try to get it from the cache again, maybe some one else added it, while we we’re waiting of the lock

result = HttpRuntime.Cache.Get(BwMailServiceAvailableKey) as bool?;

if (result == null)


// Still nothing in the cache, noe we get the RequestMailServiceAvailable and add it

result = RequestMailServiceAvailable();

HttpRuntime.Cache.Insert(BwMailServiceAvailableKey, result, null, DateTime.Now.AddSeconds(ConfigMailComponent.Current.MailServiceAvailableCache), TimeSpan.Zero);




return result.Value;



Removing a Corrupted Site Column in SharePoint

After migrating a Site Collections content data from our SP2007 environment to our SP2010 environment using Metalogix we ran into some problems with lists that did not allow us to open/update/edit/ or add new items.  We would receive this error: “Field type xxx is not installed properly. Go to the list settings page to delete this field.”

To determine what field is causing the error run this PowerShell script.  The PowerShell should terminate with an error, along with the name of the erroneous field.

$web = Get-SPWeb http://portal/site
$fields = $web.Fields
foreach ($field in $fields) {write-host $}

This script will loop through all the field types.  You should receive an error similar to this:


For our case there was a problem with Visual Fusion and it was  a Field Type of VFSLayerParams that was corrupted.  So for our case instead of ‘Field type Bool is not installed properly’.  It read ‘Field type VFSLayerParams is not installed properly’.

There is no way (that i’ve found) to remove the corrupted column via PowerShell or through UI SharePoint Designer.

The only way to remove a corrupted column is through the unsupported Microsoft way by directly deleting the column using a TSQL query on the content database itself or by completely deleting the Site Collection and starting over.

Since directly doing any type of edits on a SharePoint content database especially on a production environment will result in a non supportive state from Microsoft the best approach is to immediately open up a case ticket with Microsoft to cover your tail.

There has already been a case opened up that touches on this issue (Case #111090871991452).  I opened up one myself just to be covered.

Once the case is opened and Microsoft is aware of you making direct modifications to the databases you can proceed, or if you simply don’t care if you lose Microsoft Premier Support then you can go ahead and edit the database without opening up a case.  It’s up to you.

Okay now onto the steps.  Before you Proceed. I’M NOT RESPONSIBLE FOR YOUR FARM, so follow at your own risk.


First you will need to determine the GUID ID for the corrupted column.  To do this you will run a PS script against the Site Collection to generate a report that lists all the fields, like so.

$web = Get-SPWeb http://portal/site
$web.AvailableFields.SchemaXml | Out-File c:\temp\fields.txt

Once done open up the fields.txt file and do a search for the corrupted column.  So for my case I searched for (VFSLayerParams).

Once you find the column name, usually to the left you will find the field type GUID.

Copy the GUID down i.e. (a7756826-0a2c-45cd-a8f0-d891f236b388).  Actually you only need the last part of the GUID (d891f236b288)

Next you need to determine the Content Database this site collection lives in.  To do this you can visit Central Administration.

Central Administration -> Application Management -> View All Site Collections

This will list the Site Collection and the database it resides in.

Now that you know the Database Name time to head over to the SQL Server.

Once on the SQL Server Open up SSMS.

1.  Open up SSMS and open up a new Query against the Content Database that has the corrupted column
2.  Next select all the corrupted columns by field id GUID by running this TSQL query

SELECT * FROM [ContentDBName].[dbo].[ContentTypes] WHERE Definition Like (%d891f236b288%)

3.  This list all the columns in the Site Collection that are corrupted with that GUID
4.  Next it’s time to delete, run the following TSQL query to delete the corrupted columns.

DELETE FROM [ContentDBName].[dbo].[ContentTypes] WHERE Definition Lilke (%d891f236b288%)

5.  Make sure the columns were deleted by re-running the Select statement, if no more records return the columns have been deleted, if more records return repeat step 4.
6.  Close out of SSMS and log off the SQL Server

Now when you try to open/update/edit/add an item to the List you should be able to with no errors.

Get the webapplication by w3wp process

I you have performance issues on your SharePoint environment, it is possible to show by task manager the process sorted by memory. I you see some processes which are using a hight number of memory, you would like to know which application pool is associated with this process.

  1. Start cmd prompth.
  2. Run this command:

         Cd  C:\Windows\System32\inetsrv\

         appcmd.exe list wp

  3. Map the process number to find the correct application pool.

Tools for SharePoint User Experience (UX) Design: Wireframing

What is Wireframing?

While a scamp is the first stage in designing a site, a quick way of getting the content and functionality required planned out, a wireframe is the next stage in the process when the detail and scale of elements need to be ascertained. Similar to a scamp, a wireframe should be quick and easy to change so the process of iterations with feedback from clients will allow quick refinement of the content required.

SharePoint 2013 Axure Wireframe

Like a scamp, a wireframe should have no design elements, such as colour, fonts or imagery, ideally these should be created in one colour, only using extra colours to denote different areas or functionality, by doing this the user is forced to focus on the content and not be distracted by design elements.

Where scamps and wireframes differ is that wireframes should contain the actual content that the site requires, list items, document names, names of departments and people, navigation items etc. (or as close as possible) so that the site feels as personable and as real as possible to the users.

Another reason for the content to be accurate at this stage is that the wireframes will be produced at SS (Same Scale) as the proposed design, so if the requirements are for the site to be optimised for a minimum browser size of 1024x768px with a minimum point size of 11px then the wireframe should be created to these specifications to ensure the content will fit when we get to the design stage.

Which tools can be used to create Wireframes?

The tools for creating wireframes are wide and varied and which tool you choose to use will depend on your skill set and the projects specific requirements. Below are some of the tools available with their pros and cons:


Although not the obvious choice for a wireframe, the wireframe taking slightly longer to create initially, the finalised wireframe can have design elements quickly applied by using Photoshop layer styles to add chromes etc.

Photoshop however does a lot more than just making wireframes and therefor is a lot more expensive and a lot harder to learn than other products, so if you don’t already have a copy of Photoshop and are unfamiliar with it this is probably not the right choice.


Fireworks is probably more suited to wireframes, using symbols and states to control the look of elements which can have the design added once finalised. Another advantage with Fireworks is that the wireframe can quickly be turned into an interactive prototype.

Similar to Photoshop, Fireworks is reasonably expensive and tricky to master.


Balsamic is a tool that is designed specifically for the purpose of wireframing, giving a selection of user interface elements that can be easily dragged and dropped into position to build a layout. Balsamic is simple application and so is a skill that can be quickly learnt.

On the downside Balsamic produces wireframes that are a little closer to scamps in style so getting the content accurate is a bit harder.


Like Balsamic, Axure is designed specifically for wireframing, it comes with a selection of User Interface elements and you can create your own UI elements to add to these if required. You also have more control over the look and scale of items than Balsamic, being able to control global text styles etc.

It is a relatively simple application to learn and there are a wealth of online resources and tutorials too.

One big advantage of Axure is that once you have built your wireframes these can be quickly wired together to make an interactive prototype.

Using Axure to create Wireframe

I won’t go into too much detail on how to use Axure as there are lots of tutorials on this subject floating around the web, below I will illustrate the process of creating a simple wireframe, using the tools that come with Axure and a few extra tools we have created at Pythagoras that are SharePoint 2013 specific (which can be downloaded at the end of this article).

Step 1: Create a blank Axure document

Blank Axure Document

Step 2: Load the “SharePoint_Axure_Library” (downloadable at the end of this blog)

Click on the title of the Widgets Panel and scroll down to “Load Library” then navigate to and load the “SharePoint2013_Axure_Library”. This will add a number of UI Elements that are specific to SharePoint such as the ribbon, lists, libraries etc.

Load SharePoint 2013 Axure Library

Step 3: Add the SharePoint Ribbon from the “SharePoint2013_Axure_Library”

Drag and Drop the Ribbon from the widget library on to the page.

Drag SharePoint 2013 Ribbon into Axure Document

Step 4: Add Navigation buttons from the Axure default widget library

Drag and Drop a button on to the page, the size and text can be edited once the button has been placed.

Add Navigation Buttons

Step 5: Add the SharePoint Search Box from the “SharePoint_Axure_Library”

When dragging elements onto the page Axure has handy dialogue boxes and guides to allow pixel perfect positioning of UI elements.

Add SharePoint Search Box to Axure Document

Step 6: Add more SharePoint 2013 widgets, Axure default widgets to the page

Add More Widgets


Step 7: Export as images or generate an interactive prototype in your web browser

Axure Interactive Prototpe


This process can be repeated to create all of the required pages of the site in one Axure document, if an element is used on multiple pages then it can be created as a master and edited in one place whilst updating any page it is placed on, these wireframes can either be exported as individual images or wired together to make an interactive prototype (the process of making an interactive prototype will be covered in the next blog in the series).

The wireframe is now much more detailed than the original scamp, and because it has been created to scale we can see that the all of the required content is no longer visible within a 1024×768 screen, finding this out now rather than at the design or build stage is beneficial as we can now quickly reassess and refine the content so that the information that the client requires on the page fits within the minimum screen size specified.

Download the SharePoint2013 Axure Library here – please note, this file will only work in Axure, not the other wireframing tools mentioned earlier

Programmatically Submitting Files to the SharePoint Content Organizer

The content organizer in SharePoint 2010 is an interesting feature, particularly from an application development perspective as it gives you a fairly competent rules builder (why does it post back when you select a content type? Like seriously, Microsoft?) and routing engine, for free. We built something similar in FirstPoint for SharePoint 2007, but it was quite a bit of work. You can do all sorts of interesting things with this such as moving documents around based on metadata changes or externalizing the rules that determine where server generated documents should be routed to.The content organizer can be accessed from the Official Files web service but it can also be accessed directly when building server applications such as event receivers or custom web services. One common scenario, for example, is using an event receiver for moving a document to a different folder or library if a user changes a metadata field. If I have a list of contacts organized into folders by last name (A-C, B-E, etc.), I’d want the system to automatically move a contact into the correct folder if a contact changes his or her last name. Without the content organizer and externalized rules, you’d either have to hard code the routing rules or design and code a system to externalize the routing rules, both sub-optimal solutions compared to the content organizer.

Behind the scenes, content organizer users a class called OfficialFileCore, you’ll need to add a reference to Microsoft.Office.Policy.dll (found in the ISAPI directory) to your project. The following is some code that should give you an idea of how to call the OfficialFileCore.SubmitFile() method:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Utilities;
using Microsoft.Office.RecordsManagement.RecordsRepository;
using System.Collections;// Namespace and class omitted for formatting purposes…

static void Main(string[] args)
Microsoft.SharePoint.OfficialFileResult result = Microsoft.SharePoint.OfficialFileResult.UnknownError;
string destination = null; // New location of the file is assigned to this string.

using (SPSite site = new SPSite(“”))
using (SPWeb web = site.OpenWeb())
using (new SPMonitoredScope(“Official File Receiver”, uint.MaxValue, new ISPScopedPerformanceMonitor[] { new SPSqlQueryCounter(100) }))
SPFile file = web.GetFile(“”);
byte[] bytes = file.OpenBinary();
string fileType = file.Item.ContentType.Name;
SPFieldCollection fields = file.Item.Fields;

List properties
= new List();

// Create a RecordsRepositoryProperty for each metadata field.
foreach (SPField field in fields)
string value = Convert.ToString(

Console.Out.WriteLine(“Name:{0}, Type:{1}, Value:{2}”,
field.Title, field.TypeAsString, value);

Microsoft.SharePoint.RecordsRepositoryProperty property =
new Microsoft.SharePoint.RecordsRepositoryProperty
Name = field.Title,
Type = field.TypeAsString,
Value = value

catch (Exception exception)
// Some fields fail; not sure if they’re consequential yet!
Console.Out.WriteLine(” – Failed to process field {0}”, field.Title);

result = OfficialFileCore.SubmitFile(web, bytes, properties.ToArray(), fileType,
“”, “Charles”, false, out destination);

// Seems that you have to manually delete the file.

Console.Out.WriteLine(“1 > {0}”, result);
Console.Out.WriteLine(“2 > {0}”, destination);


In this case, the source library is the drop off library. Note that if you programmatically add a file to the library, it doesn’t actually get routed according to the content organizer rules; you’ll still have to submit it manually in the UI or use the code outlined above to actually trigger the routing.One final note: as far as I can tell, it seems that you have to manually delete the file from the source library once you successfully route the file.

Get all tasks from current user by Work Management Service Application

Work Management service in SharePoint 2013: a short overview for developers

We all know the dilemma of having our tasks scattered all over the place: some are in Exchange (Outlook), some are in SharePoint tasks lists, and some are in Project Server. Taking care of all those tasks can be a challenge. That’s why Microsoft has introduced in SharePoint Server 2013 and SharePoint Online a new service application, called “Work Management Service Application” (WMA).

This service is colloquially well-known as “Task aggregation service”, and, for the end users, it is manifested through the Tasks menu in their personal sites. Users can find all their SharePoint, Project and Exchange tasks (if opted in), aggregated and sorted, under unified “My Tasks” experience. They can sort their tasks, “pin” them (mark them as important), and mark tasks as completed – directly in the aggregated task view. Special views of “Active tasks”, “Important and upcoming tasks” and “Completed tasks” are accessible within a click. All tasks updates are synced back to their originating systems – the task providers.


Providers and refreshes

Under the hood, the whole system is based on the model of “Task providers”. Task providers are systems from which the WMA can aggregate tasks:

At the moment, three tasks providers are supported: Microsoft SharePoint, Microsoft Exchange and Microsoft Project Server. This means, that the users will see the tasks from those three sources, in their “My Tasks” area. Adding own task providers in not supported at the moment. Different providers are actually very different underlying systems, and there is no easy, “unique” way to do the aggregation and synchronization. Microsoft was planning to include an official API and methodology for adding own providers, but it never made its way in production bits, and it seems that it got a bit off the agenda. Pity, since there is great demand for it – that is actually always the first question being asked, after users learn of existence of this service application.

WMA initiates the task sync with providers through so called “provider refreshes”. In the WMA lingo, a refresh is an initiation of the task aggregation (sync) process. For SharePoint and Microsoft Project, provider refreshes are triggered on demand. That means, there is no background process refreshing the tasks for the users in some regular time intervals. Refresh is triggered at that very moment when a user accesses her MyTasks section. A small spinning circle indicates that a refresh is in progress. After refresh is completed, tasks are “reloaded”, and user gets to see her tasks. There is an artificial limit of one refresh every five minutes, not to jeopardize the overall SharePoint server performace. This limit can be changed with PowerShell commands for SharePoint 2013 (there is no GUI for Work Management Application management). For SharePoint Online in Office 365, this limit of one refresh per five minuts cannot be changed.

Provider refresh for Exchange tasks is somewhat different, and it is based on a background timer job (“Work Management Synchronize with Exchange”) which actually does the sync. The job is initially set to run every minute.

Tasks are internally cached in a hidden list in user’s My Site. That means that all the tasks which provider refresh discovers, and eventually updates, are locally stored in the WmaAggregatorList_User in the MySite.


Providers look in so called “Locations” to get the updates for existing tasks, and to discover new tasks. Locations are different and specific for each provider. For SharePoint 2013 as task provider, for example, locations are task lists in different SharePoint sites.

How does the provider know where to look, where to find the task updates for the current user? There is a collection of so called “hints”, which tells to the provider – please go and look there. In the case of SharePoint, there is an event receiver on each tasks list (new “Tasks with timeline”, content type 171), which, whenever a task for a user is added, stores that list in the hints collection. During the provider refresh, SharePoint provider looks for the tasks in that list, and, if found caches the tasks, and the list. In that process, that task list becomes a known “location”, and the tasks for the user that belong to that list are displayed under that “location” in the MyTasks.

There are also tasks without a location, so called “personal tasks”. The “My Tasks” page inside user’s My Site, is meant to be a place where users can organize their personal tasks, which do not belong to any of the tasks lists in the SharePoint Sites, or Projects. Those tasks are stored only in the “WmaAggregatorList_User” list, and, if Exchange Sync is configured, they are pushed to the Exchange, and therefore accessible in Outlook, mobile devices, etc.

All tasks without location can be “promoted” to the location tasks, what means, they can be “pushed” to a SharePoint list or to Project Server. Once when such a task gets a location, and after it is promoted, its location cannot be changed anymore (tasks cannot be moved across the locations).

Now, this was just an introduction to the WMA concepts and lingo. For anyone who wants to know more how WMA works under the hood, there is a great white paper written by Marc Boyer from Microsoft, which covers all installation and configuration aspects of Work Management Service (

Let’s see now, what can be done with WMA from a developers’ perspective.

What is in it for developers?

Even if there isn’t much developer documentation out there, WMA has one of the best and cleanest APIs in the SharePoint world, with equally good SSOM and CSOM implementations. Now, this is something that SharePoint developers have been asking all along – that CSOM APIs get more power – and Microsoft is delivering on its promise. A drawback here is that there are no REST endpoints for WMA API, so you are stuck with CSOM on the client side, for better or worse.

SSOM side API can be found in

Microsoft.Office.Server.WorkManagement.dll (in GAC)

CSOM side API can be found in

Microsoft.SharePoint.WorkManagement.Client.dll (in Hive15/ISAPI)

Since the both development models are actually parallel, the examples below will be in SSOM, but they can be 1:1 translated to CSOM side (the last example in this post will be CSOM).

Namespaces and classes

UserSettingsManager is the first thing you will want to initialize when working with task aggregation. It contains all of the user-related WMA information, like Locations, important Locations, timeline settings (how does the timeline looks like for a user), etc.

Microsoft.Office.Server.WorkManagement.UserSettingsManager usm = new UserSettingsManager(context);
//Get all locations
LocationClientCollection allLocations = usm.GetAllLocations();


UserOrderedSessionManager is used to manage WMA sessions for a user. You will need to pass a SPServiceContext (for SSOM), or ClientContext (for CSOM) to the UserOrderedSessionManager constructor, to initialize a session manager.


//Gets the session manager and create session
Microsoft.Office.Server.WorkManagement.UserOrderedSessionManager osm = new UserOrderedSessionManager(context);

Once you have your session manager, you can create a new WMA session. There are two kinds of sessions you can create: UserOrderedSession and LocationOrientedUserOrderedSession. They are for the most part the same, just that the LocationOrientedUserOrderedSession contains location info within the tasks, and this is the type of session you will usually want to use in most of the cases.

LocationOrientedUserOrderedSession uos = osm.CreateLocationOrientedSession();

This session object will be your main tool for executing task and provider refresh related actions. You will be able to create, edit, and delete tasks, to start a provider refresh, or Exchange sync, and a whole lot of the other cool things that can be done with tasks. Let’s take a look at some of them.

Querying the tasks

When you have a session manager object, you can retrieve all the tasks for a user, or filter the tasks to get only those that you need. There are seven possible filters that you can apply when querying the tasks:

  • CustomAttributeFilter
  • FieldFilter
  • KeywordFilter
  • LastModifiedDateRangeFilter
  • LocationFilter
  • PinnedFilter
  • PrivacyFilter

Most of them are self-explanatory. You can filter the tasks by custom attributes (which you can freely assign to each task, although only programmatically), by standard fields, by keywords, by last modified info, location, is task pinned (important) and task privacy. Of course, the filters can be freely combined.

It is often a requirement to get only those tasks for a user, which are stored in one SharePoint site and its subsites. Using the locations collection, and location filter, this becomes very easy to implement:


// Create a new task query

Microsoft.Office.Server.WorkManagement.TaskQuery tq = new TaskQuery();

//Get all locations which are under a specified URL
IEnumerable<Location> myLocations = allLocations.Where(a => a.Url.Contains("http://demo/sites/subsite"));
Location[] locationKeys = myLocations.ToArray();

// Create location filter
LocationFilter locationFilter = new LocationFilter() { IncludeUncategorizedTasks = false, LocationKeys = locationKeys };

tq.LocationFilter = locationFilter;

// Read filtered tasks from the task session
LocationGroupClientCollection tcc = uos.ReadTasks(tq);

This way, we got all the SharePoint tasks for a user, which are stored in all task lists in the http://demo/sites/subsite site, or in one of its subsites.

Creating a task

To create a task, we will use the session object created above. When we create a task through Work Management Application, it is initially always a personal task, stored only in the task cache list in user’s My Site. Even if we are able to set a task location when creating a task, that task is still only a personal task.

There are two overloads of the CreateTask() method, one with, and one without location. Setting the location to null, we can create the task without location even with the location-aware overload:

TaskWriteResult taskWriteResult = uos.CreateTask("My task name", "My task description", "03/24/2014", "03/27/2014", isCompleted, isPinned, "", locationId);

Task myNewTask = taskWriteResult.Result;

With those two lines, we create a task with a name, description, start date (localized string), due date (localized string), booleans that define if the task is completed and pinned, task edit link (this would be interesting if we would have our own task providers), and the location id (nullable integer).

As mentioned above, this task is still a personal task, even if there is a location info associated with it.

To “promote” this task to its location (basically, to push it to the associated SharePoint list, Project etc), we will use one of the two overloads of the Promote method. If location information has already been associated with the task, this will suffice:

taskWriteResult = uos.PromotePersonalTaskToProviderTask(myNewTask.Id);

If there was no location information, we can set it during the task promotion:


taskWriteResult = uos.PromotePersonalTaskToProviderTaskInLocation(myNewTask.Id, locationId);


Now, this task can be found in its new location as well, and the location information cannot be changed anymore.

More task operations

Once we have a task, there are numerous task related methods within the Session object. We can, for example, pin and unpin tasks to the timeline (equals to the “important” tasks in Outlook, or high priority tasks in other systems):

taskWriteResult = uos.PinTask(myTask.Id);
taskWriteResult = uos.RemovePinOnTask(myTask.Id);

Editing tasks can be done via UpdateTaskWithLocalizedValue method. There is an enumeration WritableTaskField, that defines which task fields can be updated. This is important, since tasks are coming from different providers, which might have different task properties (SharePoint tasks are not the same as Exchange tasks), and those properties are basically the least common denominator, which can be found in each task provider. Those are:

  • Title
  • Description
  • StartDate
  • DueDate
  • IsCompleted
  • EditUrl

Please note IsCompleted property here: by updating it, you can set the task status to “completed” (100% task progress in some providers), or not completed (0% progress).

This line of code would update the task description:

uos.UpdateTaskWithLocalizedValue(myNewTask.Id, WritableTaskField.Description, “New Description”);

This line of code sets the task to the “completed” status:


uos.UpdateTaskWithLocalizedValue(myNewTask.Id, WritableTaskField.IsCompleted, “true”);


Deleting task is also quite simple, even if the word “deleting” might not be a right expression here. The method DeleteTask actually removes the task from your MySite timeline:

TaskWriteResult twr = uos.DeleteTask(myNewTask.Id);

For personal tasks, which live only inside the timeline, this is ok – they are really deleted. But the provider tasks are not – only their cached copy is removed from the timeline, and the tasks can still be found in the respective SharePoint lists and Project tasks. If you need to delete them from there, you will need to call respective provider specific APIs.

Working with provider refreshes

As mentioned above, a provider refresh is a process of retrieving and caching tasks for a user. It is done on demand, with no background job processing the tasks. Refresh will be started at that moment, when a user access its “My Tasks” area. There is an artificial limit of 5 minutes between provider refreshes, which can be changed through PowerShell for SharePoint on premise.

Provider refresh can also be initialized programmatically, from the task session:

CreateRefreshJobResult refreshResult = uos.BeginCacheRefresh();

The resulting CreateRefreshJobResult will tell us if the provider refresh process has started successfully (it will be probably not yet completed). If the provider refresh process could not be started from some reason, CreateRefreshJobResult will hold the error information and it’s Correlation Id (mostly caused by the imposed 5 minutes limit).

If CreateRefreshJobResult was executed successfully, it will contain an Id of the newly created provider refresh process, which can be used to check the provider refresh job status. You can check the general status, the status for each task provider separately, and update status for each task location separately.

This short code snippet explains it all:

RefreshResult rr = uos.GetRefreshStatus(jobId);

Console.WriteLine("Refresh state: " + rr.AggregatorRefreshState.ToString());

Console.WriteLine("Corellation id: " + rr.CorrelationId);

Console.WriteLine("Refresh finished: " + rr.RefreshFinished.ToShortDateString() + " " + rr.RefreshFinished.ToShortTimeString());



Console.WriteLine("Provider statuses:");


foreach (ProviderRefreshStatus prs in rr.ProviderStatuses)


Console.WriteLine("Provider key: " + prs.ProviderKey);

Console.WriteLine("Provider name: " + prs.ProviderLocalizedName);

Console.WriteLine("Root location id: " + prs.RootLocationId.ToString());

Console.WriteLine("Provider Refresh started: " + prs.RefreshStarted.ToShortDateString() + " " + prs.RefreshStarted.ToShortTimeString());

Console.WriteLine("Provider finished: " + prs.RefreshFinished.ToShortDateString() + " " + prs.RefreshFinished.ToShortTimeString());





Console.WriteLine("Location update results:");


foreach (LocationUpdateResult lur in rr.TaskChangesByLocation)


Location loc = allLocations.Where(a => a.Id == lur.RootLocationId).FirstOrDefault();


Console.WriteLine("Location: " + lur.RootLocationId);

Console.WriteLine("Added: " + lur.AddedCount.ToString());

Console.WriteLine("Active added: " + lur.ActiveAddedCount.ToString());

Console.WriteLine("Removed: " + lur.RemovedCount.ToString());

Console.WriteLine("Updated: " + lur.UpdatedCount.ToString());


The result from this code snippet will look like the screenshot below. We can see, that there is only one provider active (SharePoint, in this case), and that 3 tasks have been updated in the location with id 3:

You can retrieve a provider refresh history for a user, with all provider refreshes from some time interval until now.

Those few lines of code will enable you to check refresh status for the past 7 days, and to analyze potential problems – for each unsuccessful provider refresh, Correlation Id associated with the refresh status, for the further analysis.

RefreshHistory rh = uos.GetRefreshHistory(DateTime.Now.AddDays(-7));


foreach (RefreshResult rr in rh.Refreshes)


// Check refresh status


And on the client side?

I have mentioned already that the CSOM side have been implemented with almost the same methods as the server side. To finish this blog post with a goodie, I will create a Windows 8 store app, with a Windows Runtime Component which will reference the Work Management APIs (“Microsoft.SharePoint.WorkManagement.Client.dll” from Hive15/ISAPI), and fetch the task data.

You will, of course, need a ClientContext to create UserSettingsManager (instead of SPServiceContext which was used within the server side model).

ClientContext context = new ClientContext("http://server");


//user settings manager

Microsoft.SharePoint.WorkManagement.Client.UserSettingsManager usm = new Microsoft.SharePoint.WorkManagement.Client.UserSettingsManager(context);


//get all locations from usm

Microsoft.SharePoint.WorkManagement.Client.LocationClientCollection locations = usm.GetAllLocations();



//user ordered session manager

Microsoft.SharePoint.WorkManagement.Client.UserOrderedSessionManager osm = new Microsoft.SharePoint.WorkManagement.Client.UserOrderedSessionManager(context);


//location oriented session

Microsoft.SharePoint.WorkManagement.Client.LocationOrientedUserOrderedSession uos = osm.CreateLocationOrientedSession();


//task query

Microsoft.SharePoint.WorkManagement.Client.TaskQuery tq = new Microsoft.SharePoint.WorkManagement.Client.TaskQuery(context);


//read tasks

Microsoft.SharePoint.WorkManagement.Client.LocationGroupClientCollection tcc = uos.ReadTasks(tq);


//batching done, client execute




//iterate through results

List<Microsoft.SharePoint.WorkManagement.Client.Task> allTasks = tcc.ToList<Microsoft.SharePoint.WorkManagement.Client.Task>();


List<SpTask> tasks = new List<SpTask>();

foreach (Microsoft.SharePoint.WorkManagement.Client.Task task in allTasks)


//iterate through results, create an IEnumerable that can be bound to the View


The task data will be bound to an items page in the C# Windows Store app. This will work with both SharePoint on premise, and with Office 365. The result could look like:

I hope that this short walkthrough the Work Management Service Application development model, could give you a brief overview of the things that can be done. I deeply feel that WMA is somehow neglected in the SharePoint 2013 and Office 365, although it offers some great user scenarios.