Thursday 18 December 2014

SharePoint Designer 2013 - Common Errors with Simple Solutions

There are any number of generic and frustrating errors that one may encounter when working with SPD and workflows. The most infuriating are those that prevent publishing the workflow and are not caused by the operator. This post lists a few of my favourites - and the workarounds I've applied to overcome them. I expect it to grow over time. ;-)

"Errors were found when compiling the workflow... Unexpected error on server associating the workflow"

This is without doubt the most common and generic error facing all workflow designers. It often occurs after trying to publish an error-free workflow that then throws an - (X, X) Activity 'IDXX' validation failed: ... - type error.

While there are many proposed solutions to this -- IIS resets, app pool recycling, a read-only text file in the app pool's temp directory, even web.config modifications -- none of them reliably worked for me.

The simplest and most effective solution has been to simply delete the contents of the ProxyAssemblyCache directory for the user on the machine you're running SPD from.

This directory can be found in the following location:

C:\Users\USER\AppData\Roaming\Microsoft\SharePoint Designer\ProxyAssemblyCache

Property 'DurationUnit' has invalid value

This error occurs periodically when attempting to publish a workflow with an approval action. I'm not sure why it occurs or why it picks the DurationUnit variable but this is the only one I've ever seen affected.

The complete error is:

(0, 0) Activity 'ID4' validation failed: Property 'DurationUnit' has invalid value. Field type 'System.String' does not match with the expected type 'Microsoft.Office.Workflow.Actions.DurationUnit'.)

Like others who've encountered this I was perplexed when I couldn't find 'DurationUnit' in the workflow parameters or variables. That's because it's sneakily hidden (along with many others) in the Properties for the approval action, which you can get to by right-clicking the action.

To resolve the error, just click the ƒx symbol next to the parameter in question, ensure that field from source is Parameter: Duration Units and click OK.

Approval Workflow Error on Rejection

This occurs with the OOTB approval workflows and the Start Approval Process action (which uses the same core task processes. When a user clicks Reject on the task, the workflow errors out without any real indication as to why. If you check the ULS logs (and your diagnostic log settings are set appropriately) you may see something like this:

Workflow Infrastructure 98d4 Unexpected System.InvalidOperationException: CompositeActivity cannot transition to 'Closed' status when there are active child context still exist for child activity.

Ignoring the horrific grammar, the key clue here is "active child context still exist for child activity". This led me to believe the task process was not properly exiting for whatever reason. Some claim it's a long-standing bug in the Microsoft.Office.Workflow.Actions assembly. Reverting this to an older version was not something I was going to entertain.

After scrutinising every last aspect of the task processes and nearly giving up, I finally found a solution. Once again the fix turned out to be a simple one.

  • Click the approval action to open the task process screen.
  • Click the Change the behavior of the overall task process link in the Customisation section.
  • Scroll your way down to the When The Task Process Completes event.
  • Within the "Else" clause you should see an End Task Process action. Remove it.

Please feel free to comment on any other errors you come across often and I'll do my best to find solutions.

Wednesday 10 December 2014

People Picker field not displaying in New/Edit forms

I recently ran into a perplexing problem with a list on which I had created a new People & Groups field, restricted it to a particular group, added it to the InfoPath form and republished.

Everything worked as expected during my tests but UAT picked up something interesting. The field was not being rendered in New and Edit forms.

After cursing InfoPath and SharePoint generally for an hour or so, it came to light that only people in the Site Owners could modify the value for the field.

I decided to remove the group picker restriction and, sure enough, the field was suddenly available. Hmmmmm....but this is not the solution I was after so I reapplied the restriction to the group I wanted and then changed the groups settings so that everyone could see the members. That did it!

TO be honest, SharePoint and InfoPath were actually doing the right thing by applying the group's security settings to the field.

Now that I'm aware of this particular quirk I can see some valuable uses for it in future. If only group level permissions could be applied for every field we'd really be cooking with gas. :D

Monday 28 July 2014

SharePoint Virtual Directory Mapping Mayhem

I had updated a 2010 VS solution which contained references to a custom CSS file and several image resources. Upon deploying it to my 2013 farm I was surprised to see that all these links were broken.

All my references used the traditional tilde followed by "/_layouts/" and then the end path - i.e. ˜\_layouts\SolutionFolder\myfile.ext - which looked just fine and matched the same format I've always used. In addition, the deployment location for Layouts and Images directory within VS was using the {SharePointRoot} token and correctly placing everything within its correct location on the server.

So I changed the URL in the open browser window to point to a few OOTB application pages and images and noticed hit and miss results with these too! What was going on??

I carefully checked and compared file permissions, toyed with different file formats and extensions... There was no pattern to this madness!

I dug a little deeper and noticed that the files which were successfully loading also existed in the 14 directory. Hmmm... This led me to take a look at the virtual directory mappings in IIS and this is what I found:

The _layouts virtual directory actually maps to SharePoint 2010’s 14 hive!

One can only assume that this was done for backwards compatibility with 2010 solutions, which can also be deployed to the same farm.

Lesson learnt. Always include the hive version in the path when referencing server-side resources.

Friday 2 May 2014

Get Web Part Usage and List Instances [A PowerShell Journey continued]

In my last post I dealt with listing all the features associated with deployed solutions to the farm, and then showing where they were activated. Armed with that information and what I found in the manifest for each feature, I now have what I need to attempt locating all the pesky instances of these custom web parts and lists.

You may be wondering why I'm going to all this trouble. Well, in the absence of source code, these sites will not upgrade. So my intention is to identify all the customisations so that I can either remove (or rebuild) them safely, before deactivating the features they belong to. And also, I just LOVE tinkering with PowerShell. :D

Get WebPart Usage

I wrote this as a function to make it more re-usable. Pass in the webapp URL and webpart name, and it will go through every ASPX document - Publishing, Wiki and Web Part page - and return the page URL, webpart DisplayTitle and webpart Name for each found. The reason I return the name is that I used the -like comparison operator to allow for loose (wildcard) searching. This is extremely handy when dealing with multiple webparts using the same canonical naming syntax.

I went down the webfolder/files collection path, as opposed to hitting the list/item collection, because I needed to recurse through the Forms subfolders to find any list form templates that had been customised.

The function first runs through every folder and subfolder and adds the (ASPX) files to an array called $AllPages. It then proceeds to get the SPLimitedWebPartManager for every file and interrogates the SPLimitedWebPartCollection for a matching webpart name.

The output proved invaluable to me as it showed that not only were some webparts present in customized list forms, but also in master and layout pages. I see a re-branding project in my near future. :\

Get All Lists by TemplateID

Next I wanted to get a list of all the web templates for my root sites. As I already knew where the list template features were activated, and at what scope, I didn't need to iterate through every webapp, site and web again.

The code below grabs the list templates for each root web in the $webs array that I'm interested in. It then outputs a GridView for each web's SPListTemplateCollection.

The grid is sorted by template ID (Type_Client). As you may know, best practice dictates that any custom list template have an ID of 10000 or higher, so this make identifying all custom templates a simple matter. You could even specify a Where clause to return just those templates but I find this list to be a handy reference anyway.

I absolutely love GridViews. In fact I could write several articles on them alone. Few people realise their power. Built-in column sorting and filtering, and selective row selection, can be passed through to the next pipeline object using the new -PassThru function in PowerShell 3. The GridView actually performs all those complex and fidgety sorting and filtering tasks on your behalf. If your next pipeline object is a CSV file then this essentially means you can re-use the same grid to generate custom reports without having to alter your code. [end rant]

So now I've got my list template IDs I want to locate every list instance that's been created using that template in the target webapp(s). The script itself is pretty straightforward. It prompts for a webapp URL and template ID and again it iterates through every site and web.

It took my a little while to discover that the list template ID was stored in List -> Rootfolder -> Properties in a property named vti_listservertemplate. But once I had that the rest was easy.

The output simply provides the list title and URL for each match.

I've modified the code so that both scripts can be both be run consecutively. In this way you can reference your list template ID and then add it at the prompt.

Wrap Up

I hope these last two posts help someone else trying to achieve the same or similar goals. I was fortunate that I only had to deal with list templates and web parts. I can only imagine the headache if custom field types, event receivers and other elements had been included. In my next post I'll likely be detailing the steps taken to eradicate all the deployed customisations found so that I can attempt to deactivate the features and retract the solutions. Unless the source code decides to suddenly materialise...

Thursday 1 May 2014

List all SharePoint Solutions, their Features and where they're Activated [A PowerShell Journey]

I recently inherited a farm with a lot of deployed customisations and no source code or documentation for any of it. In my experience this happens all to often and trying to work out what's been deployed and where can be very laborious indeed. Enter PowerShell!

Get a list of all solutions, then just the deployed solutions.

That's a start but: Where were they deployed? Do they contain features? If so, what is their scope and where are they activated?

Thanks to Google I found a great piece of scripting by Régis Boussion on TechNet which really got me moving. [cf. How to get all site features and custom features from sharepoint sitecollection?]

What this returns is a list of EVERY Feature in the farm, grouped by its Solution. I have modified this to filter the output to only deployed solutions.

So now I have a list of deployed solutions and the count, name and scope of each feature it contains. But I want to know more.

Features - Scope, Activation, Location

The code below iterates through every web app, every site and every web so use it with caution. The end result returns output for each solution: solution name, its features and scope, and the URLs where it's activated. I say activated because that's what's returned by the Features property. And for my purpose I was only interested in activated features.

my.sharepoint.webparts.solution.wsp (2)
my.sharepoint.webparts Some Web Part (Web)
 > http://url
 > http://url/subsite
my.sharepoint.webparts Another Web Part (Site)
 > http://url

And the code:

I was hoping to take this one step further by drilling into the feature object to list any associated web parts, lists and so on but sadly this isn't possible.

In my next post I'll be dealing with locating web part usage and list instances for these active features.