Tuesday, 29 January 2013

SharePoint Content Organiser and Custom Routing

I recently received a request to spend some time reviewing whether or not Content Organiser Routing could be extended and customised.

The request came out of a problem encountered by one of our consultants when he set up a Content Organiser Rule which routed a document to a separate Site Collection. The destination Site Collection then had its own Content Organiser rules to add a document into a specific library existing in the site and implementing a folder structure based on the metadata included with the document. The folder structure would pre-exist and be set up using a custom Content Type and pre-populated metadata which the document, when it was added into the folder, would inherit.

This worked fine when a folder matching the metadata in the document already existed, however, if the folder did not already exist, despite setting the Content Organiser rule to create a new folder, SharePoint displayed a strange "security validation time out". After a little digging, I founder references to a "security validation time out" error from Microsoft who had already resolved the problem in the form of a requestable Hotfix (KB2596584 - http://support.microsoft.com/kb/2596584) which as far as I could see did not form part of SharePoint SP1 (which is what the server was running). I requested, downloaded and installed the Hotfix (after snapshotting our VMware Server) and it resolved the issue and functionally the system was working as expected.
 
That was great, so from a client perspective, there was no more odd message that didn't mean much, and not only that but the Content Organiser rule now appeared to working properly.
 
However, based on our requirement it was necessary that the folder that was created automatically would have to use our own custom Content Type, not the standard Folder Content Type. Despite removing the New Folder options from the destination library and making the custom Content Type available, the Content Organiser would always create any new folder using the standard Folder Content Type, which was pretty much what I expected. So, I started looking into Custom Routers.
 
A Custom Router can be created using the simple Interface ICustomRouter. It implements a single method OnSubmitFile in which you can do some additional or alternate processing before handing back to the EcmDocumentRouter. Registering a Custom Router is straight-forwards. I used a very simple Console Application as I was only researching the issue, but ideally this would be a Web or Site Feature that registers the Custom Router on activation (and removes it on deactivation).

Once the Custom Router is registered (using the EcmDocumentRoutingWeb.AddCustomRouter method) it becomes available through the UI when you add or edit a Content Organiser Rule:



 
When you register the Custom Router the first parameter is the Name - this is what appears in the dropdown above. Once this is set up on the Content Organiser Rule it means that the Content Organiser does its normal processing up to a point and then makes the call into the Custom Router. It appears from what I've seen that the call is made to the Custom Router just prior to actually saving the file to its final destination, therefore, any processing that may be required to make this happen would have already been done, i.e. creating a new folder, which I'll come back to in a moment.

The Custom Router's OnSubmitFile method call can return one of two CustomRouterResult options: SuccessContinueProcess and SuccessCancelFurtherProcessing (obviously no room for failure here)...

As I just mentioned, if you are setting a rule up to create a folder if it doesn't exist (which we are in our scenario), regardless of which result you return, the folder will always get created. The difference in result types is more apparent from what happens to the routed file. Returning SuccessContinueProcessing does exactly what it says, it carries on after the Custom Router code and performs the standard and expected behaviour, i.e. routes the document according to what rules you have and actually performs the save to the final destination. SuccessCancelFurtherProcessing, however, doesn't process any further, as the name suggests, therefore, as you can see in the MSDN example, it useful if you are going to handle what happens yourself and you don't need the out-of-the-box routing to do anything. What I would say is that returning SuccessCancelFurtherProcessing will mean that the file is lost: I returned this value during my testing and the routed file disappeared from the Drop-Off Library as expected and never appeared in the destination library which only makes me think that this option is really only useful if you are going to implement the saving of the file yourself.

Back to our scenario, I was able to use the Custom Router to reset the metadata and Content Type of the already created folder (as we get a reference to this in the OnSubmitFile method) which fitted what we were looking for. I had a quick try and yes, it worked, however, there is a caveat. What I expected was that items subsequently added into the updated folder would inherit the metadata set on the folder. In my short trial of this, it didn't work that way, so I suspect I'm not setting something or some configuration is missing, so just be aware that it may be an issue.

Hopefully this has been of some use.
 

Thursday, 25 October 2012

X-UA-Compatible Meta Tag Not Working

​You may or may not be aware that you can force IE to render a web page is a specific document mode, which means that an IE9 browser can be forced to render a page as if it was IE8 or IE7.  Why you'd do this is most likely due to the fact that forcing an newer browser to render like an older one (for instance, forcing IE9 to render like IE7) provides a convenient baseline when trying to style a page.

You do this by adding the X-UA-Compatible meta tag to the head block of a page as follows:

<meta http-equiv="X-UA-Compatible" content="IE=8" />

This particular line forces IE to render using IE8 mode.  You can read more about it here: http://msdn.microsoft.com/en-us/library/cc288325(v=vs.85).aspx.

There are a couple of caveats to adding this meta tag.  The first one is that it must be the first meta tag in the head block (there are a coupld of exceptions to this).  The second one is not so obvious, and is the main reason for this article.

If you use conditional comments to render the opening HTML tag of a page (see http://paulirish.com/2008/conditional-stylesheets-vs-css-hacks-answer-neither/ for details about this) the meta tag just plain doesn't work.  It doesn't matter where you place it in the head block, it just doesn't work.  If you have the same issue, the way around it, as it turns out, is rather simple if a little weird: move it to before the conditional comments like so:

<meta http-equiv="X-UA-Compatible" content="IE=8"/>
<!--[if lt IE 7 ]> <html class="ie6"> <![endif]-->
<!--[if IE 7 ]>    <html class="ie7"> <![endif]-->
<!--[if IE 8 ]>    <html class="ie8"> <![endif]-->
<!--[if IE 9 ]>    <html class="ie9"> <![endif]-->
<!--[if (gt IE 9)|!(IE)]><!--> <html class=""> <!--<![endif]-->

I've tested this and it appears to continue to work as expected with no downside (apart from ugly HTML).  Hopefully this will help someone out there.

Thursday, 16 February 2012

Cookies...and not the munching kind

What am I talking about? Well, due to an amendment to the law (the Privacy and Electronic Communications (EC Directive) Regulations 2003, and the new Directive 2009/136/EC) in May last year, the way information is stored by technology is being changed, and primarily how cookies should and can be used and stored - hence the nick-name for this amendment: "The Cookie Law".

The UK government has given businesses a year to comply with the changes, which means that as from May 2012, any organisation that does business in the UK (and EU) is affected.

To find out more: http://www.ico.gov.uk/for_organisations/privacy_and_electronic_communications/cookie_rules_prepare.aspx

Just so you don't panic too much, this doesn't appear to affect intranets! It only applies to public-facing websites.

Wednesday, 15 February 2012

Learning jQuery

If you ever wanted to learn jQuery but couldn't find the time or the discipline to do so, you can get some daily force-fed lessons by visiting http://learnjquery.tutsplus.com/ and signing up for the "30 days to Learn jQuery" course from Tuts+.

If you're starting out learning this stuff it should provide some structure (hopefully) to your initial learning.  Have fun.

Monday, 30 January 2012

SharePoint Formatted String Control

I've come to the conclusion that a little known but widely used control, the FormattedString control in the Microsoft.SharePoint.WebControls namespace, is a very useful control. Any search through the Control Templates delivered with SharePoint shows how often this control is used when rendering output through SharePoint. It works in the same way a String.Format would in code, only it's something that can be added to an ASCX or ASPX asset.

Let's have a closer look.

In a publishing scenario, if you have some HTML into which you need to inject a value from the current page then you may be able to use the FormattedString control to create the HTML, as you might using String.Format. This can include HTML (i.e. "&gt;p&lt;" instead of "<p>") and any other server-side control output.

In a simple example, to do this you simply add in the usual "{0}" indexed tokens and then, as child controls, you add in the field values. Here's an example, after which I'll explain a little more:

<SharePointWebControls:FormattedString runat="server" 
FormatText="&lt;p&gt;{0}&lt;/p&gt;&lt;p&gt;{1}&lt;/p&gt;" 
EncodeMethod="NoEncode">
    <SharePointWebControls:FieldValue 
runat="server" FieldName="Title" />
    <SharePointWebControls:FieldValue runat="server" 
FieldName="Description" />
</SharePointWebControls:FormattedString>

The 2 child controls (FieldValue) render out the value of the 2 page field values as strings which are then used by the FormattedString control to replace the 2 tokens respectively. You could, as child controls, use any server control to output more complex examples should you wish, or your own custom controls. The render sequence always processes child controls first, so whatever the output is from the child control is used. You can have as many tokens as required. Another scenario might be to get the server-relative URL of the site, which you can do by using the SPUrl function in an ASP Literal control.

Going back to my example, the FieldValue control itself, is another little-documented control which I frequently use as it renders the value of a field without much or any of the surrounding HTML, which results in cleaner markup. Using it in the above context makes sense as we only want the actual values, not the additional HTML a control might output.

More information can be found here: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.formattedstring.aspx and for the FieldValue control, some limited information can be found here: http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.fieldvalue.aspx.

Friday, 23 December 2011

Problem restoring a PowerShell backup

I had a problem today attempting to restore a backup I had taken using PowerShell.  I received the following error in PowerShell when running thr Restore-SPSite command:

"Restore-SPSite : Your backup is from a different version of Microsoft SharePoint Foundation and cannot be restored to a server running the current version. The backup file should be restored to a server with version '4.1.10.0' or later."

I checked my SharePoint version numbers against the server where I had taken the backup and it all looked fine. I took another backup in case the first one had become corrupt (even though I had already restored it successfully several times before). I rebooted and restarted my VM, but all to no avail.

In a last ditch attempt, I decided to delete 2 empty content databases that were set up on my machine, and created a new one to replace them and tried again.

To my surprise, it worked. So, if you have the same problem, try removing content databases (if you can).

Friday, 2 December 2011

Usability Testing

Browsing through some of the SPC2011 conference materials, I came upon a useful website that provides usability testing from the perspective of how a user would interact with your web design. You simply provide a web design image or HTML I believe and a series of tests are run to assess how your design is used by real-world users.

The click responses to questions about the design are grouped and displayed so you can see whether what you thought was a prominent design for something important actually does the job of attracting user interest.

It's not a free site, but a test is only $9 (about £5.70 at today's price) which is possibly well worth the pay-out to get some useful design feedback upfront of any development work.

Check out http://www.intuitionhq.com.