Monday, 9 November 2009

ContentTypeRef vs ContentTypeBinding

There seems to be some uncertainty around the use of the ContentTypeRef element in Schema.xml and the ContentTypeBinding element in your elements file. The master—Andrew Connell—indicates both should be used but various discussions (see links below) suggest

you can use the ContentTypeRef to create a list with a content type, or you can use a ContentTypeBinding to add it later.

I personally found this discussion somewhat hard to follow and Andrew's post just says DO IT without any additional explanation; this post documents my own findings around the why.

While I always use ContentTypeRef in my Schema.xml files because my custom lists are backed by a custom content type, I hadn't come across ContentTypeBinding in a list context until recently—or if I had, I assumed it was unnecessary since everything just works without it. My understanding of content types leads me to believe each list has its own internal content type or at the very least, its own set of fields (the latter is certainly evident in the duplication of fields in Schema.xml and the file used to provision custom fields).

All's well, or so I thought until I had to programmatically enumerate a list item's fields: I noticed my custom fields were listed twice. Creating a new list from the Custom List template and assigning my custom content type did not result in this duplication so I knew something was up with my custom list definition. For some reason, the problem was not evident when inspected using my best friend SharePoint Manager 2007.

As expected, removing the fields included in Schema.xml that are duplicated in my custom content type/fields broke the list.

It seems telling Schema.xml about my custom content type in the ContentTypeRef doesn't cut it—the ContentTypeBinding element is required to effectively map the list fields against the fields referenced in the content type. After adding a ContentTypeBinding element and enumerating a new list instance, the duplicates are gone.

Like Andrew illustrates, I add the ContentTypeBinding element to my ListDefinition.xml file between the ListTemplate and ListInstance elements (your file may be named differently):

<ContentTypeBinding ContentTypeId="0x0100CB568E1363E18245810A4EF25B057CCE" ListUrl="Lists/MyList" />

All's well once again... until next time!

Ps. Andy Burns asks himself:

I wonder what happens if you try to create a list definition without a content type reference?

Andy, you can’t leave me hanging like that man!!! I dropped the ContentTypeRef element from my Schema.xml file and while no errors were reported and a list instance only reported using the custom content type specified in ContentTypeBinding, NewForm.aspx was a dog’s breakfast with some aspects of the content type ignored. For example, I’ll often hide the Title field in my list definitions and yet there it was (sure, ShowInNewForm/ShowInEditForm might address this but that’s not the point). Fields also weren’t ordered the way they were in the content type definition.

Links

Thursday, 5 November 2009

Sorting and filtering doesn't work on custom HTML list field

After deploying a custom list today I noticed, much to my annoyance, list items were not respecting the OrderBy FieldRef specified in my view and sorting the list manually in either direction on the field in question had no effect. Worse, the Show Filter Choices menu item led to the display of a #Render Failed error message in the central pane and the Application event log and SharePoint logs reported the following:

Unknown SQL Exception 306 occured. Additional error information from SQL Server is included below.  The text, ntext, and image data types cannot be compared or sorted, except when using IS NULL or LIKE operator.  The ntext data type cannot be selected as DISTINCT because it is not comparable.

The #Render Failed issue seems to be a fairly well-known bug and was apparently been fixed in the June 2009 WSS Cumulative Update although it's unclear whether that problem is related to my general sort/filter problem.

The problem field did have an edit control block attached in my case and while I expected that to be the culprit, changing the field type from HTML to text resolved the problem for me. Not my preferred approach but acceptable in this particular case.

Wednesday, 4 November 2009

ListTemplate Name attribute doesn't resolve $Resources

Further to my previous 0x81070215 post, I've since discovered this error code also crops up when specifying an invalid ListTemplate value for the Name attribute.

In my case I was attempting to supply the value from a .resx file something like Name="$Resources:List_Name;". While resources are successfully resolved on other ListTemplate and List attributes, this doesn't seem to be the case with Name and its value must be specified explicitly; incidentally, the Name must match the name of the folder containing the list definition. The OOB 12-hive examples I've cross-checked also specify a literal value.

While this error code was presented in the UI, the SharePoint log files revealed how SharePoint was parsing the attribute value:

Cannot open "schema.xml": no such file or folder.
Failed to retrieve the list schema for feature {1B3FC94C-2FC6-4528-B968-4E91843C2005}, list template 13133; expected to find it at: "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\Template\Features\TeMCorporateBannerListFeature\$Resources:List_Name;".
Unknown SPRequest error occurred. More information: 0x81070215

No biggie since DisplayName does handle resources for localisation however in this case I'm attempting to use resource files for consistency and to simplify maintenance across my list definition.

For reference, 0x81070201 seems to mean about the same thing (a similar error message I received after reverting the Name value to a literal with a typo).

Friday, 30 October 2009

0x81070215 Means Dodgy List

After some more hacking around with a custom list SharePoint gave me this error code: 0x81070215

Basically I’d mangled a list definition while an earlier version of the list still existed. The easy solution in my case (dev) was to simply fire up SharePoint Manager 2007 and use the UI to delete the offending list (stsadm –o forcedeletelist –url http://spsite would have probably done the same thing). In a more serious environment, you’d probably need to redeploy the list bits as they were when the list was created.

Control template "ListForm" does not exist

I have no idea how I caused ListForm not to exist but after some clumsy tinkering with a custom schema.xml file, the main section of NewForm.aspx page was coming up blank and the AllItems.aspx page for all lists in all sites across my dev farm refused to render the normal menu.

The SharePoint log file was telling me:

Control template "ListForm" does not exist

Examining a list’s NewForm.aspx file in SharePoint Designer (which of course makes me feel dirty all over) you’ll note it holds a ListFormWebpart. “Control template” would further point me to the _controltemplates virtual directory—mapped to \12\TEMPLATE\CONTROLTEMPLATES, but this directory doesn’t contain a ListForm.ascx or ListFormWebpart.ascx file.

Thankfully the Application event log entry was more precise:

Load control template file /_controltemplates/DefaultTemplates.ascx failed: The file '/_controltemplates/DefaultTemplates.ascx' does not exist.

A quick check of \12\TEMPLATE\CONTROLTEMPLATES and of course DefaultTemplates.ascx was nowhere to be found. Copy/paste from a functional server and we’re back in business. Now to figure how what caused it to be deleted in the first place…

Wednesday, 28 October 2009

Activating a feature containing a content type generated from Andrew Connell's stsadm commands generates 100% CPU load

I've used AC's WCM Custom Commands for STSADM successfully in the past and they're extremely handy. In short, I create my site columns and content types in the SharePoint UI and then run Andrew's GenSiteColumnsXml and GenContentTypesXml to dump the XML required for incorporation in a feature. Today I hit a wee snag when attempting to activate a feature containing fields and content types generated from these commands: the operation wouldn't complete until terminated forcefully and the CPU was meanwhile running at 100% (infinite loop anyone?).

Luckily JoeB came across the same problem in the past and was kind enough to post his fix in the comments on Andrew's blog (although I also noticed another commenter noted the issue in production after implementing JoeB's fix...). Andrew says these commands were built using the 80-20 rule: they'll get you 80% of the way there and you're on for the rest. Fair enough—the commands are extremely handy and I reckon they go well beyond the 80% mark. That said, these are some of the things I fix up after generating the output; I'll list JoeB's fix here too:

Fields

This makes updating the feature easier:

  • Add the DisplaceOnUpgrade="TRUE" attribute

I've read these aren't meant to be included explicitly but the documentation, useful as it is, indicates they're optional anyway:

  • Remove the SourceId attribute
  • Remove the StaticName attribute

These can go without any consequence I've noticed:

  • Remove the Version attribute
  • Remove the Required="FALSE" attribute

These seem to come out if you muck around with the fields too much in the UI:

  • Remove the PITarget attribute
  • Remove the PrimaryPITarget attribute
  • Remove the PIAttribute
  • Remove the PrimaryPIAttribute
  • Remove the Aggregation attribute
  • Remove the Node attribute
  • Remove the ContentType field altogether (SharePoint Manager 2007 indicates it's added automatically even if not specified)

Content Types

JoeB's fix to the 100% CPU issue:

  • Add NamespaceURI="http://schemas.microsoft.com/sharepoint/v3/contenttype/forms" to the XmlDocument element

(Note you may also be able to remove the XmlDocuments node altogether).

Friday, 23 October 2009

No SharePoint MVPs in Western Australia

This is an unfortunate situation… there are so many top-notch SharePoint guys (and gals) working proactively in the community and doing great work in WA with major clients. That said, with only five SharePoint MVPs in Australia I’d say we’re under-represented as a country!

You can nominate yourself or someone else here: https://mvp.support.microsoft.com/gp/mvpnominate

Western Australia SharePoint MVPs

Tuesday, 20 October 2009

Running ISO Recorder on Windows Server 2008 x64

When trying to copy a DVD to an image using ISO Recorder v3.1 on a Windows Server 2008 x64 machine, the Next and Finish buttons were greyed out despite correctly selecting the From and To locations. As I have to run Nero Express Essentials as an admin (right-click, Run as administrator), I tried setting the ShellExec.exe file below C:\Program Files\Alex Feinman\ISO Recorder to run as admin on the Compatibility tab to accomplish the same thing. When that didn’t work, I found I had to click the Show settings for all users and select Run this program as an administrator on the second Compatibility for all users window.

This doesn't seem to work for all functions; for example, attempting to burn the created ISO to disk fails to populate the Recorder drop down with the local optical drive and I can't complete the operation.

In general I must say ISO Recorder looks like it's going to do the job I want it for quite nicely. I created an image from a DVD by right-clicking on the DVD drive icon in Windows Explorer and it popped an 1.7GB .iso out the other end in a few minutes. I've burned ISOs with Nero in the past but can't seem to find the right settings on the version I'm using currently (I'm lumped with .nrg files). ISO Recorder hits the nail on the head so I'm sticking with it ;-)

Tuesday, 13 October 2009

Approval workflows: approval by any approver

Configuring an approval workflow to request approval from a group of approvers and deem the workflow complete after any single person has completed their approval task is trivial but it's not that obvious. I certainly missed it on my first pass through today!

The Assign tasks to radio button options on the workflow customisation page focuses on the parallel versus serial distinction. If you've got multiple people configured as approvers, you're either assigning tasks to everyone in the list or you're assigning tasks sequentially to everyone in the list; in both cases every approver has to complete their task before the workflow is deemed complete.

In the past, we've noticed a behaviour where approving a page doesn't seem to do anything—the page status stubbornly remains as Waiting for approval no matter how many times or how many different ways you attempt to approve the page and the fact that you’re a site collection administrator web application administrator, and farm administrator makes no difference!  (Without email configured on the server and perhaps some SSPs bits in place, as was the situation in our case, no one will ever know additional input is required unless you're checking the workflow status). In all likelihood, the root cause of this "problem" was an approval pending completion by virtue of being assigned to twenty people. Doh!

But I digress. Adding approvers to a dedicated Approvers group is the logical thing to do in most cases to simplify approver management. Instead of changing multiple workflows as employees come and go, it's much easier to manage a SharePoint group or an AD group. Selecting the approvers list is easy but how do you get the "any approver" bit happening?

The answer lies in the check box directly below the Approvers selection input field: Assign a single task to each group entered (Do not expand groups). Think about it long enough and it actually starts to make sense—only one approver needs to complete their task before the workflow is deemed complete, or to paraphrase: “assign the task to the Approvers group and no one person in particular.” This option isn't selected by default so select it and you're golden.

SharePoint Approval Workflow - Any Approver

Wednesday, 30 September 2009

Web site performance monitoring tools

Having gone through the pains of learning about web site performance and applying that understanding to a MOSS site (www.westernaustralia.com), the latest post on the SharePoint Team Blog about optimising sharepoint.microsoft.com caught my eye. I’ve been meaning to cover the performance nitty gritty from our experience for ages now but, for the moment, suffice it to say we fixed most of the problems faced by our global audience and now use a commercial performance monitoring service called Gomez to keep an eye on things. Gomez competes with the likes of Keynote if you’re in the market.

Commercial solutions like this cost a lot of money because they’re essentially distributing test agents all around the world and measuring full page load times from your site at a configurable interval. Response metrics are stored for trending analysis and comparison with other sites. Despite the cost, these tools are worth the money if you know your site is experiencing performance issues (if not the data gets boring really fast).

Firebug, YSlow, and Fiddler are great tools for analysing performance and will give you both page load time and page weight but they’re all executing from your desk; if your web server is down the hall or in the same city (or country) you may not have a clear picture of how latency is affecting your site users on the other side of the world. If you’re targeting a domestic audience that’s obviously not a problem but if you’re targeting a global user base and you’re attempting to do so with SharePoint you need to ensure everything about your site is optimised—not just just the server configuration. The SharePoint Team Blog post highlights the fact SharePoint (MOSS 2007) is not optimised for internet sites out of the box.

As the cost of these performance measurement services is prohibitive—especially in this tough economy, it’s interesting to see where the free services are going feature-wise. I mention the SharePoint Team Blog post specifically because the author cites a new tool I hadn’t yet come across: http://www.webpagetest.org/ I’ve previously evaluated Pingdom but their offering was still developing a year ago (they offer both free and paid services).

The webpagetest.org site is painful on the eyes but the data they provide at no cost is comprehensive. The site currently allows you run tests from one of three nodes (the US, UK, and New Zealand), meaning an adequate global coverage (we test westernaustralia.com from seven locations matching the site’s target markets).

The tool reports the results from a full page test, meaning the page and all of it’s supporting resources are requested, providing a realistic picture of how long it takes to load the page and all CSS/Javascript/images/XML files/Flash files/etc. Some of the freebie offering I’ve seen in the past only reported the page HTML load time, which will often be negligible.

In addition to giving you a screenshot of the page, which is often useful to compare what the world sees versus what you think they’re seeing, you get full waterfalls of data for a first visit and what they call a repeat view (a subsequent request for the same page with a primed browser cache), and an item by item optimisation checklist.

webpagetest waterfall and optimisation

I’m impressed!