ItemAdding event – is the list item a file or a folder?

In event receivers other than ItemAdding it is a simple task to determine if the current item is a file or a folder. You would write something along the lines of:

However in the ItemAdding event properties.ListItem is null. This is because the list item is yet to be created. In order to determine if the current item is a file, you should instead try this:

You are welcome!

New Button Order ‘Bug’ and Document Sets

The Quirk

Using the SharePoint GUI to modify list or library settings with the goal of changing the ‘new button order’ or ‘default content type’ may yield unexpected results.

Under List Settings, this is the functionality in question
Under List Settings, this is the functionality in question

Confusingly (or perhaps to avoid confusion) the control which displays the ordering of the content types for the New button, along with their visibility, does not show the items in the order in which they have been set.

Initial view of the New button order control
Initial view of the New button order control

As an example of this, I will set a content type marked as not-visible to have an order of 1.

I have am marking a non-visible content type as the default content type (position 1)
I have am marking a non-visible content type as the default content type (position 1)

I press OK to save the form. Upon returning to the form it would be reasonable to expect to see the control rendered with the non-visible content type in position 1 as we have just set it to be this way.

I would have expected the control to render like this. IT DOES NOT!
I would have expected the control to render like this. IT DOES NOT!

However, this is not the case. You will see the content types listed in same order as before the change was made.

After making the change, the control is rendered in exactly the same way as it was before the change
After making the change, the control is rendered in exactly the same way as it was before the change

The control always displays the visible content types at the top of the list which are then sorted by order number. The content types which are not marked as visible are then shown in alphabetical order. Importantly, this is just how they are displayed. The actual content type order may be different depending on how you have set it.

So who cares?

Most likely there are very few people who will even notice this let alone care. In fact, in nearly all scenarios it makes perfect sense to render the control this way. That is, until you want to have a default content type that is not visible under the new button. At this point the control may become very misleading. There is really just one case where the control does not accurately display the functional impact of changing the content type order. When you set a non-visible content type as the default content type (position 1), it is still treated as the default content type, despite how the control may render it.

Why would you want a default content type that is not visible under the new button?

In my case it was because in the library’s root folder only document set content types and a particular document content type (A) were allowed. However, inside the document set only a different document content type was allowed (B). By setting the document set’s allowed content type you can have the new button display content types that are not listed as visible in the list settings. All good, you can only create documents of content type B inside the document set and only create document of content type A outside the document set.

My issue arose when a user uploaded a document to the document set. An uploaded document ignores the document set’s allowed content type and is created as the first content type listed on the New button order in the list settings. To workaround this issue I set content type B as position 1, which works as expected despite how the control may render it.

ULS Log Analyser

Infrastructure contacted me to complain that one of our SharePoint environments was logging too much data (via the ULS) and it was becoming unmanageable (an Operations Management tool like SCOM has not been configured). Looking through many gigabytes of text, even with a free tool like ULSViewer, it is difficult to be confident that you are correctly identifying the most common issues, it is an inaccurate art at best.

That is why I wrote a log analyser as a PowerShell script which will process ULS log files and, using fuzzy comparison, create a report of the most frequently occurring log entries.

I am very well aware that this is not necessarily useful information in many cases (hence I had to write this script myself). Nevertheless I found it useful in my scenario and I hope that some of you may as well.

Just in case you are interested: using this script I was able to declare with certainty that logging by the SPMonitoredScope class made up almost 30% of total log entries. This will be reduced by explicitly stating the log severity in the class constructor as verbose and maintaining a log level of  Medium for the SharePoint Foundation : Monitoring diagnostic logging category.

A few things of note:

  • You may want to add to or remove from the set of replace statements in order to increase/decrease the ‘fuzziness’ of the comparison. Adding a replace statement for removing URLs may be a good candidate if you wish to increase matches.
  • The script loads entire files into memory at once. Be aware of this if you have very large log files or not much RAM.
  • The output file is a CSV, open it with Excel.
  • By default the script will identify and analyse all *.log files in the current directory.
  • If you cancel the script during processing (ctrl+c) it will still write all processed data up until the point at which it was cancelled.

I quite enjoy PowerShell-ing so expect to see more utilities in the future.

SharePoint Maintenance Mode Automation with PowerShell

In an ideal world, downtime (scheduled or otherwise) would be avoided entirely. Unfortunately, there are plenty of reasons why a web site may need to go into a scheduled maintenance mode. It’s important that this is done correctly and performing such as task across a farm manually can be error prone and tedious.

 

Maintenance

In my case, I wanted to automate the activation/deactivation of a maintenance page across a SharePoint farm with multiple Web Front End servers. The same script would be run across a number of different environments with differing topology depending on requirements (development, QA, staging, production, etc).

 

As of .NET 2.0 a very useful feature was introduced which makes putting a single web application (on a single server) into maintenance mode straightforward. If you drop a file named “app_offline.htm” into the IIS web application directory for your web site it will “shut-down the application, unload the application domain from the server, and stop processing any new incoming requests for that application. ASP.NET will also then respond to all requests for dynamic pages in the application by sending back the content of the app_offline.htm file”. [quoted from ScottGu’s Blog].

 

Leveraging this technique I have written a script to provision (or remove) a maintenance page correctly across all the required servers in a SharePoint farm.

 

A few things of note:

  • There are a number of SharePoint specific PowerShell commands being used so, as it is, this script cannot be used for other, non SharePoint, ASP.NET web sites. I would like to hear from anyone who modifies it for another use.
  • The user running the script will need to have enabled PowerShell remoting (Enable-PSRemoting -Force) as well as permission to Write and Delete from the file system of the other servers.
  • As it is, the script drops the app_offline.htm file for every web application zone. In my case, I only wanted to block users from accessing the zone configured to use our custom claims provider. I have left in the check for this in case you find yourself in a similar situation.
  • The maintenance page must be entirely self-contained. By this I mean that all CSS and JS must be embedded and even images must referenced using inline base64 representations. See here for an easy way to achieve this.
  • If want to perform an IISRESET and stop/start the  SharePoint Timer Service at each WFE before taking down the maintenance page then uncomment the relevant lines.

If you find this helpful please subscribe to our feed and feel free to leave a comment with your thoughts.

Intermittent Workflow Error – Failed on start (retrying)

A custom SharePoint 2010 workflow which I wrote was occasionally failing (perhaps 1 in 10) when auto-starting upon the addition of list item with a ‘Failed on start (retrying)‘ status. I’ve dealt with this error in the past and it is almost always caused by invalid workflow code (bad correlation tokens etc, there’s plenty about this elsewhere) but in those cases the failure is consistent.

Looking into the logs I found an unexpected error: “AutoStart Workflow: System.ArgumentException: New instances of this workflow template are currently disallowed“. The workflow association was NOT set to ‘no new instances’. In the case of my particular workflow, it was performing a considerable amount of work upon start including creating a dynamic amount of tasks that in most cases counted more than twenty.

With a lack of other options I modified the workflow with a delay immediately after start so that the workflow would sleep and then create tasks at the next timer interval. The error still intermittently appears in the logs but the workflow runs anyway (I believe it fails to run during the first timer interval when this happens, but retries at the next at which it works). Clearly this solution is not ideal, but has resolved my issue from a functional perspective.

If I come across a more elegant solution or any functional problems with this solution I’ll be sure to update this post. Good luck.

List view sort order bug

SharePoint was once known for it’s unfortunate list of quirky bugs. As of SharePoint 2010 there are definitely less of these to contend with but some still remain – like this one. The sort order for a list view can get rendered incorrectly when editing the view.

When you define a view programmatically it is up to you to create the XML which defines it. A common view query for a tasks list may be to show all items in descending order so that the newest tasks appear at the top of the list. As such:



SPView view = list.Views["All Tasks"];
view.Query = "<OrderBy><FieldRef Name='ID' Ascending='False' /></OrderBy>";
view.Update();

This will update the view just as you or I would expect. However, there is a significant problem here. When a user modifies this view in the future (via the ViewEdit.aspx) the form will show the view is sorted on ID (correct) but the ‘Show items in ascending order’ radio button will be selected (incorrect). If the user now saves the form, perhaps having added another column, the incorrect sort order will be persisted. To avoid this issue you must capitalise the Ascending attribute value as such:



SPView view = list.Views["All Tasks"];
view.Query = "<OrderBy><FieldRef Name='ID' Ascending='FALSE' /></OrderBy>"
view.Update();

I’m unaware of anywhere within SharePoint that providing upper-case boolean attributes is bad practice so I would recommend always using FALSE instead of False and TRUE instead of True.

Powershell function arguments and the array operator

If you are a C# developer that is new to Powershell, or at least new to writing Powershell functions with typed parameters you will likely come across the following error:

Cannot convert the "System.Object[]" value of type "System.Object[]" to type "<type of first argument>"

The reason for this error is most likely because you are passing a comma separated list of arguments as you would in C#:

myfunction arg1, arg2, arg3 or perhaps even myfunction(arg1, arg2, arg3)

In both of these cases you are in fact passing an array of objects as the single and only parameter. Considering this, the error message makes perfect sense. In Powershell the comma is an array operator (see here) and arguments should be passed to a function delimited only by a space character. Like so:

myfunction arg1 arg2 arg3

This brings up another question though: “how come I wasn’t getting an error when I had untyped parameters (or string type parameters)?”

This is because under the covers the arguments list is just an object array and the parameters are positional – they retrieved by indexing into the arguments array. When you are passing a single parameter that is an object array you are passing in the arguments array itself. When the parameters are typed such that they can be auto-converted from an object type (eg string) then it will work as expected.

The _layouts web.config for customErrors

There is a web.config file under the _layouts folder. This is worth being aware of as you may notice that files that you access from the _layouts folder may not behave as you would expect. This came to my attention when I was getting the following error:

”To enable the details of this specific error message to be viewable on remote machines, please create a tag within a “web.config” configuration file located in the root directory of the current web application. This tag should then have its “mode” attribute set to “Off”.

This initially surprised me as I knew that I had already done as such and had recently seen the default error screens when I was building web parts on content pages.

As the web.config under the layouts folder is deeper in the site hierarchy, any elements defined here will overwrite those defined at the web application level. By default the customErrors element exists at this level and it must be set accordingly to your needs as well.

As always, be careful when editing web.config files and always make a backup beforehand.

Visual Studio Developer Tips

Visual Studio is an excellent IDE for working with Microsoft technologies. However, it isn’t perfect and can crash or hang from time to time. After experiencing an issue with the IDE during a debugging session recently, I came across a setting which improved my Visual Studio experience and thought it was time to bring together some of my favourite tips.

 

1.       Navigate To (CTRL+COMMA)

This outstanding useful key combination brings up the ‘Navigate To’ dialog which allows you to find almost anything -files, classes, methods, properties. It is so easy and so fast that, IMO, it should be used instead of the Solution Explorer whenever you know the name of anything you are looking for.

NavigateTo
The “Navigate To…” dialog

 

2.       Debug > Delete All Breakpoints (CTRL+SHIFT+F9)

Regularly deleting all breakpoints can greatly improve you debugging experience within VS. The performance impact upon attaching to a process per of individual breakpoint is negligible. However, after some time, presumably accelerated by merging from source control, the solution can become corrupt (I use the term ‘corrupt’ tentatively because the solution is still functional) such that loading symbols upon attaching to a process can take an exceptionally long time. Deleting all breakpoints (using the command, not individually) refreshes all references and fixes this issue.

 

3.       Solution Explorer Collapse And Sync (Solution Explorer Tools in VS2010)

Installing this VS add-on provides what can be very useful macros for the solution explorer depending on how you use it. It provides functionality such as ‘close all branches’ and ‘open to the current branch’.

The Solution Explorer Tools toolbar

You can find it here.

Personally, I quite like the built-in ‘Tools > Options > Projects and Solutions > General > Track Active Item In Solution Explorer’ which ensures that the solution explorer is always open to currently active file, but I know a lot of users will hate the way it jumps about.

 

4.       Dark Themes

Even with relatively fresh young eyes, staring at a white screen is painful after a few long sessions. Bring on the dark themes. Using a theme with a dark grey background saves my eyes and keeps me in the zone! There are many great ones and a handy designer for creating your own. With the release of VS2012 there is now even greater granular semantic colourisation.

“Son of Obsidian” from StudioStyles

 

5.       Deactivate Implicit Property Evaluation

Tools > Options > Debugging > General > (uncheck) “Enable property evaluation and other implicit function calls”

The impact of this is that properties aren’t evaluated unless you inspect them individually (explicitly). This means that you can no longer view all properties on an object by calling it in the immediate window – you have to inspect properties one-by-one. As SharePoint objects have dozens of properties this can make a noticeable difference when debugging SharePoint code. As such, your mileage may vary depending on what you are debugging and the relative performance of your debugging environment.

 

6.       Integrate Third Party Diff Tool

You can swap in external programs to perform your file merging and file diffing activities. Personally, I think that WinMerge is fantastic, especially after fine tuning the comparison settings (e.g. skip white space, block detection, etc.), but whatever you find is your favourite utility for these actions it almost certainly isn’t the default. Paul Bouwer has already blogged in detail about how to plug it in:

WinMerge in action

These are tips that I expect to be useful for nearly any developer working with Visual Studio. Depending on what you are working on it is always worth a quick web search to see what else is out there to aid your efforts and help you work smarter.

With Windows 8 and SharePoint Apps being a development focus, the web development improvements in VS2012 will be obvious. It also includes SharePoint asset designers, a SharePoint profiler and more built in SharePoint templates among many other features.