Showing posts with label Features. Show all posts
Showing posts with label Features. Show all posts

Thursday, 8 April 2010

stsadm –o activatefeature –force suppresses error messages

Oh the pain: your solution builds and deploys with no error messages but something’s awry, your feature files are where they need to be in the .wsp/.cab and the target file system but SharePoint is none the wiser. So you lather, rinse and repeat (er, rebuild, redeploy, re-activate) to no avail; everything’s working yet nothing’s working!

We have our stsadm –o activatefeature commands tucked away in our deployment scripts and they just happen to use the –force parameter. This is normally fine, except when the feature breaks; in this case the feature is still force activated—as requested—but error messages are suppressed… in other words everything seems okay but it’s all really all horribly wrong. Even the event log is clean as a whistle.

So to figure out what’s going on, drop the –force attribute (you may need to deactivate the feature manually first), and reactivate. Behold the error message in all its glory.

Tuesday, 10 November 2009

Adding the Edit Control Block (ECB) to an additional/different list column

This is how I add the ECB menu to a different column. All changes are made within the context of my list's Schema.xml file.

To start, I already have a custom text field defined within the Fields element:

<Field
Description="$Resources:Field_Caption_Description;"
DisplaceOnUpgrade="TRUE"
DisplayName="$Resources:Field_Caption_DisplayName;"
Group="$Resources:Group_DefaultName;"
ID="{1ac83cea-5b25-4e2f-ae43-5116e005ca97}"
Name="Caption"
Type="Text"
/>

To this I add a new computed field that references the existing field:

<!-- Edit Control Block (ECB) Context Menu -->
<Field
AuthoringInfo="(with menu)"
ClassInfo="Menu"

DisplaceOnUpgrade="TRUE"
DisplayName="$Resources:Field_Caption_DisplayName;"
DisplayNameSrcField="Caption"
ID="{09868F6C-7419-4db3-9C1A-434598ABE010}"
Group="$Resources:Group_DefaultName;"
Name="CaptionContextMenu"
ReadOnly="TRUE"
Type="Computed"
>
<FieldRefs>
<!-- First FieldRef points to parent field -->
<FieldRef ID="{1ac83cea-5b25-4e2f-ae43-5116e005ca97}" Name="Caption" />

<FieldRef ID="{3c6303be-e21f-4366-80d7-d6d0a3b22c7a}" Name="_EditMenuTableStart" />
<FieldRef ID="{2ea78cef-1bf9-4019-960a-02c41636cb47}" Name="_EditMenuTableEnd" />
</FieldRefs>
<DisplayPattern>
<Field Name="_EditMenuTableStart" />
<HTML><![CDATA[<a onfocus="OnLink(this)" href="]]></HTML>
<URL />
<HTML><![CDATA[" ONCLICK="GoToLink(this);return false;" target="_self">]]></HTML>
<!-- Points to parent field -->
<Field Name="Caption" />

<HTML><![CDATA[</a>]]></HTML>
<Field Name="_EditMenuTableEnd" />
</DisplayPattern>
</Field>

Note DisplayNameSrcField points to the original field, as does the <Field> element in the DisplayPattern section.

Finally in my view's ViewFields element, I modify the FieldRef pointing to my original field to point to my ECB column:

<FieldRef Name="CaptionContextMenu" />

A few things to note:

  • When I first tried this with the original field set as type HTML, it didn't work; I ended up changing the field to a text field. I haven't tried other field types.
  • /_layouts/sitemanager.aspx presents the view in a similar but slightly different way to that presented by the list itself (e.g. /Lists/MyList/AllItems.aspx); Site Manager tends to always add the ECB on the second column whereas the latter tends to do a better job doing what you tell it to do. [Update: I use the DocIcon field in position #1 to work around this issue... it shows up as a little document icon with a column name of Type--which I haven't been able to hide. It's clickable in the AllItems.aspx-style view at least so not completely useless and it obviously shoves the ECB to a potentially meaningful field in the second position (you can alternatively use ID but this may not not make sense if you're ordering list items).]

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

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).

Saturday, 25 July 2009

Content Type ID Structure

Creating a custom content type in a feature requires you specify the ID attribute.

Content type IDs are constructed hierarchically and you can trace the lineage of a content type through its ID. A custom content type will often derive from the Item content type—the most basic content type you can use. Item is derived from the System content type and contains the ever-present Title field (Title can be hidden if necessary). Note the System content type is sealed, meaning it can’t be derived from in your code.

The ID of the System content type is 0x and the Item content type appends 01, giving you 0x01. A separator must be used between all subsequent IDs appended to the base string; 00 is used for that purpose, giving you 0x0100.

A custom content type will need its own ID appended to the base system-item-separator ID and the best way to do that is using a GUID without the braces and hyphens (use guidgen.exe, included with Visual Studio).

Here’s an example with the base system-item-separator ID combination bolded for clarity:

0x0100C1FA419A4F94429C8F40DB576B211FD7

To create additional custom content types derived from an existing custom content type, add an addition separator and GUID:

0x0100C1FA419A4F94429C8F40DB576B211FD700B87CFA11-7687-4171-B67B-E1DFE20BBB86

Content type IDs are limited in length to 1024 characters so if you’re running out of room or just don’t like using GUIDs, a content type ID can optionally be specified with two digits other than 00. WSS uses this convention so be wary of any clashes with your own custom content types.

If you’re working with pages, note the Page content type derives from System Page content type, which in turn derives from Document which in turn derives from Item. The Page content type ID is therefore

0x010100C568DB52D9D0A14D9B2FDCC96666E9F2007948130EC3DB064584E219954237AF39

Additional Resources:

http://msdn.microsoft.com/en-us/library/aa543822.aspx

Friday, 15 May 2009

Blocking SharePoint Designer from Accessing Your Site

In a recent TechEd discussion panel comment, my favourite SharePoint MVP Eric Shupps mentions the ability to block SharePoint Designer from connecting to a SharePoint server and modifying content.

Why is SharePoint Designer a bad thing?

  • It’s free; every man and his dog can download it, potentially install it, and potentially break your sites
  • It can potentially be used against production—which if you follow a regimented deployment process is all wrong as changes can be made any ol’ time
  • It customises (or ghosts, if you prefer) pages thereby severing the link between the artefacts you’ve conscientiously built into a solution package and featurised;  uncustomising these artefacts may not be possible, depending on the changes that were made, or you’ll need another way to fix things up.
  • Artefacts created by SPD are created in the content database and can’t be moved easily between environments (eg. from dev to UAT to prod)
  • It modifies your files and injects stupid attributes that only it cares about
  • It’s buggy and it sucks and crashes and it’s too complicated for business analysts and too wrong for developers and it’s FrontPage rebranded and so on.

Eric’s comment got me digging and I found this new tool on CodePlex that installs a feature allowing admins and content editors to disable access to a site using SPD. Although a site definition can be altered directly to limit access by SPD this won’t affect existing sites, can’t be unlimited at any point in the future using any obvious mechanism, and is all a bit weird.

No SharePoint Designer is implemented as an HTTP Handler so it doesn’t touch the content database or much of anything. It’s still early days but definitely a “watch this space” kind of effort.

An alternative tool uses AD groups to limit access and this approach uses group policy to simply block SPD from running (and this MSDN blog entry is comprehensive if nothing else!).

Resources:

http://www.msteched.com/online/view.aspx?tid=efa154e2-6c06-4a76-ab3c-e9d71ebf0ff2
http://nospd.codeplex.com/
http://support.microsoft.com/default.aspx/kb/940958
http://blogs.msdn.com/sharepointdesigner/archive/2008/11/25/locking-down-sharepoint-designer.aspx

Monday, 27 April 2009

Delete web parts from the Web Parts gallery when a feature is deactivated

I don’t normally pay a lot of attention to what SharePoint does when deactivating features, retracting solutions and deleting solutions; I’m usually much more interested in what happens as things are installed: did I get everything right in manifest.xml? Did all the files get deployed correctly? And so on.

Now I’m a bit of a neat freak and to date I’ve always been reasonably impressed with how SharePoint actually deletes the folder wrapping a feature when the solution is removed and generally cleans up after itself. I wasn’t so excited, however, when I realised SharePoint still leaves some junk behind—where it’s visible to users and clients in the Web Parts gallery, no less. If I request a feature be deactivated, I expect it to be deactivate in full, not leave web parts listed in the Web Parts gallery that when added to a page will simply break.

I was also noticing the modified date in the Web Parts gallery wasn’t updating as I redeployed and reactivated my solutions/features. I’m not clear on this but I wonder if that means the web part definition isn’t getting updated in the site collection (it was suggested elsewhere).

A quick search reveals this is normal SharePoint behaviour but luckily two guys have come up with an elegant solution to remove spurious web parts from the gallery when the containing feature is deactivated; the only downside is the feature must be explicitly deactivated—simply retracting the solution and even following up by deleting the solution from the solution store won’t trigger the feature receiver’s FeatureDeactivating method. Of course these web parts can be deleted manually but we all know that sucks.

Anyway, it’s a fine start: Greg Galipeau kicked off a first draft that removes a single web part based on the feature name and Trent Foley applied some nice LINQ wizardry to remove all the web parts listed in the feature’s element definitions. Nice work guys! My contribution? Well apart from saying thanks, I’ve tested out Trent’s implementation and proven it works brilliantly; I’ve also swapped out the var declarations for concrete types to assist with my understanding and because I like being explicit (I won’t bother posting the code unless someone requests it).

Next step: page layouts? ;-)