February 2, 2012 - 11:59, by Steven Van de Craen
Categories: SharePoint 2010, Taxonomy, Event Receivers, .NETIssue
Today I was troubleshooting a customer farm where Managed Metadata would remain empty in SharePoint, even though it was filled in correctly in the document’s Document Information Panel.
Digging through the internal XML structures of the DOCX and also the Content Type Schema and Field XML, I couldn’t find a reasonable explanation.
The library was configured with multiple Content Types, but the issue occurred only on some of them. It appeared that for those Content Types, the Managed Metadata field was Optional, not Required.
I tried reproducing that configuration in a new document library but there everything kept working, so the issue had to be with the existing library.
Further analysis, comparison and reflection showed that the problematic library was missing some Taxonomy-related Event Receivers.

There appear to be four (4) Taxonomy Event Receivers:
- TaxonomyItemSynchronousAddedEventReceiver (ItemAdding) and TaxonomyItemUpdatingEventReceiver (ItemUpdating) are added when a Managed Metadata field is added to the List
- TaxonomyItemAddedAsyncEventReceiver (ItemAdded) and TaxonomyItemUpdatedEventReceiver (ItemUpdated) are added when “Metadata Publishing” is enabled in the List Settings

The problematic library at the customer was lacking the first set of Event Receivers, which are responsible for syncing the hidden field.

Fix
I’ve written a one-off script (Console App) that loops all lists with a Managed Metadata field on all sites in the site collection and ensures the Taxonomy event receivers. That code was taken directly from TaxonomyField.AddEventReceiverIfNotExists.
using System;
using System.IO;
using System.Text;
using System.Windows.Forms;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Taxonomy;
class Taxonomy_Fix
{
public static StringBuilder sb = new StringBuilder();
public static string nl = "\r\n";
public static string url = "http://intranet";
public static void FIXALL()
{
using (SPSite site = new SPSite(url))
{
foreach (SPWeb web in site.AllWebs)
{
FixTaxonomyReceiverOnWebLists(web);
web.Close();
}
}
File.AppendAllText(String.Format("c:\\{0:HH_mm_ss}.txt", DateTime.Now), sb.ToString());
MessageBox.Show(sb.ToString());
}
private static void FixTaxonomyReceiverOnWebLists(SPWeb web)
{
for (int i = 0; i < web.Lists.Count; i++)
{
SPList list = web.Lists[i];
if (HasTaxonomyField(list))
{
sb.AppendFormat("{0}{1} has Taxonomy Field{2}", url, list.RootFolder.ServerRelativeUrl, nl);
EnsureTaxonomyHandlers(list);
}
}
}
private static bool HasTaxonomyField(SPList list)
{
bool result = false;
foreach (SPField field in list.Fields)
{
if (field is TaxonomyField)
{
result = true;
break;
}
}
return result;
}
private static void EnsureTaxonomyHandlers(SPList list)
{
AddEventReceiverIfNotExists(list.EventReceivers, SPEventReceiverType.ItemAdding, typeof(TaxonomyField).Assembly.FullName, "Microsoft.SharePoint.Taxonomy.TaxonomyItemEventReceiver", "TaxonomyItemSynchronousAddedEventReceiver", SPEventReceiverSynchronization.Synchronous);
AddEventReceiverIfNotExists(list.EventReceivers, SPEventReceiverType.ItemUpdating, typeof(TaxonomyField).Assembly.FullName, "Microsoft.SharePoint.Taxonomy.TaxonomyItemEventReceiver", "TaxonomyItemUpdatingEventReceiver", SPEventReceiverSynchronization.Synchronous);
}
private static void AddEventReceiverIfNotExists(SPEventReceiverDefinitionCollection eventReceiverCollection, SPEventReceiverType type, string assembly, string className, string receiverName, SPEventReceiverSynchronization sync)
{
if (eventReceiverCollection == null)
{
throw new ArgumentNullException("eventReceiverCollection");
}
if (string.IsNullOrEmpty(assembly))
{
throw new ArgumentNullException("Valid assembly name required");
}
foreach (SPEventReceiverDefinition erd in eventReceiverCollection)
{
if (erd.Assembly == assembly && className == erd.Class && type == erd.Type && erd.Synchronization == sync)
{
sb.AppendFormat("\t>> no action required{0}", nl);
return;
}
}
SPEventReceiverDefinition erd2 = eventReceiverCollection.Add();
erd2.Name = receiverName;
erd2.Type = type;
erd2.Assembly = assembly;
erd2.Class = className;
erd2.Synchronization = sync;
erd2.Update();
sb.AppendFormat("\t>> Added TaxonomyEvent Receiver{0}", nl);
}
}
Disclaimer: not responsible for this code. Run at own risk. Feel free to adapt or improve as desired or required.
Conclusion
I can’t really explain why only some Content Types were affected. I’m guessing the Optional/Required setting of the Managed Metadata field is involved somehow, but I didn’t really confirm that through testing.
Also not sure why the Event Receivers were missing in the first place. It could be because some “questionable” actions happened during the setup of the site, but it could as well be a bug in SharePoint 2010 RTM or later.
January 26, 2012 - 13:09, by Steven Van de Craen
Categories: SOAP, SharePoint 2010Today we were experimenting with SharePoint 2010 CSOM (Client Side Object Model) and we noticed strange errors such as HTTP ERROR 417 were returned. When browsing to Lists.asmx and Sites.asmx we got the following error:

The top XML element 'string' from namespace 'http://schemas.microsoft.com/sharepoint/soap/' references distinct types System.String and Microsoft.SharePoint.SoapServer.SoapXml.SoapXmlElement. Use XML attributes to specify another XML name or namespace for the element or types.
One of the MSDN Forums’ answers stated that you could use direct WSDL link (http://url/_vti_bin/sites.asmx?wsdl) and that would work, which it does in the browser but not for CSOM. And besides, I don’t like these kind of errors on one of my environments while other environments work fine.
Turned out someone had disabled HttpGet, HttpPost and HttpPostLocalhost protocols in the web.config of the ISAPI folder (maps to _vti_bin).

Uncomment those lines and your Web Services should be fine again.
January 5, 2012 - 11:22, by Steven Van de Craen
Categories: SharePoint 2010, SearchPosting this for personal reference:
SharePoint 2010 - Configuring Adobe PDF iFilter 9 for 64-bit platforms
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\14.0\Search\Setup\ContentIndexCommon\Filters\Extension\.pdf]
@=hex(7):7b,00,45,00,38,00,39,00,37,00,38,00,44,00,41,00,36,00,2d,00,30,00,34,\
00,37,00,46,00,2d,00,34,00,45,00,33,00,44,00,2d,00,39,00,43,00,37,00,38,00,\
2d,00,43,00,44,00,42,00,45,00,34,00,36,00,30,00,34,00,31,00,36,00,30,00,33,\
00,7d,00,00,00,00,00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Office Server\14.0\Search\Setup\Filters\.pdf]
"Extension"="pdf"
"FileTypeBucket"=dword:00000001
"MimeTypes"="application/pdf"
sps2010pdf.reg
January 3, 2012 - 06:24, by Steven Van de Craen
Categories: SharePoint 2010, Excel Services, Office Web ApplicationsRecently a colleague wanted to display a with Excel Services rendered workbook inside a cross-domain iframe:
But because Excel Services and Office Web Apps render a HTTP response header X-FRAME-OPTIONS: SAMEORIGIN this won’t work and you get “This content cannot be displayed in a frame”

Not used to seeing such a straight-forward error :)
I did a bit of investigating but couldn’t find an easy way to configure this through UI or Powershell, so I was left with the following options:
- Strip the header in a reverse proxy (between client and SharePoint server) like Apache or ForeFront
- Remove the header with development of a HttpModule
PermissiveXFrameHeader
I wrote up a quick HttpModule that can be activated by Web Application Feature and will remove the X-FRAME-OPTIONS header no questions asked.
You might want to adapt the code for additional checks on referrer, querystring, client, or similar for conditional removal of the header (see final note below).
Installation and activation
Download from here (Ventigrate Codeplex Repository)
Deploy the WSP (farm solution) to the SharePoint Farm
STSADM -o addsolution -filename Ventigrate.Shared.PermissiveXFrameHeader.wsp
STSADM -o deploysolution -name Ventigrate.Shared.PermissiveXFrameHeader.wsp -allowgacdeployment -immediate
Activate the Web Application Feature to the Web Application referred to in the iframe

Final note
The header was designed to protect against clickjacking. If you intend to use the above solution keep this in mind and plan for it accordingly.
December 27, 2011 - 10:43, by Steven Van de Craen
Categories: jQuery/JavaScript, SharePoint 2010Here’s a small fix for which I didn’t have time to investigate more properly:
Issue
The User Profile Page of another user shows a link “Add as colleague” when that user isn’t already a colleague:

It seems however that the link behind “Add as colleague” directs to the Default AAM URL rather than the current URL you’re using.
Example:
When browsing to the page using http://intranet the link will refer to http://internalserver. This is not the desired behaviour (think mixed authentication or extranet scenario’s).
Quick fix using jQuery
<script type="text/javascript" src="/my/Style Library/js/jquery-1.7.1.min.js"></script>
<script type="text/javascript">
$(function()
{
var el = $('.ms-my-addcolleague');
if (el.attr('onclick') != undefined)
{
el.attr('onclick', el.attr('onclick').replace('http:\\u002f\\u002finternalserver:80', ''));
}
});
</script>
I’m referencing jQuery in the Style Library of the My Site Host, which you need to add or modify the link. I’ve hardcoded the internal URL (default zone public URL), might be better to look that up dynamically but as said this is a quick fix.
You can view the source of your own User Profile Page to find the internal URL for your environment.
You can add this in a Content Editor Web Part to the User Profile page and it should work just fine making the link relative.
Applies to
I’m seeing this issue in a SharePoint 2010 + Service Pack 1 + August 2011 Cumulative Update (14.0.6109.5002). Might be fixed in a later CU or SP.
December 7, 2011 - 16:32, by Steven Van de Craen
Categories: Event Receivers, Sandbox Solutions, SharePoint 2010SharePoint 2010 and SharePoint Online (Office 365) allow for custom development in the form of Sandbox Solutions. Your code is restricted to a subset of the SharePoint API but allows you do most regular operations inside a Site Collection.
Problem
Here’s a scenario that fails every time and everywhere:
- Create a sandboxed Event Receiver that is registered to ItemUpdating
- Create a sandboxed Web Part that does an SPListItem.Update() from the SharePoint Object Model
- Watch how the sandbox errors out with the following message
[SPUserCodeSolutionExecutionFailedException: Unhandled exception was thrown by the sandboxed code wrapper's Execute method in the partial trust app domain: The sandboxed code execution request was refused because the Sandboxed Code Host Service was too busy to handle the request.]
- Now just edit the item from the SharePoint UI and watch how that works wonderfully well
Sandbox Request Architecture
So what’s going on here ?

In light of this you might conclude that there’s no possible communication between two sandbox code requests (the Web Part and the Event Receiver). As good an explanation as any, so feel free to chime in.
Other things
Here are some other things I stumbled upon while researching this issue:
- ItemUpdated is not affected and works fine
- You cannot make your “after” events Synchronous in a Sandbox as they won’t fire
- (Sandbox) Event Receivers can only be registered declaratively in the Feature XML
- The certificate checking issue (crl.microsoft.com) has the same error message, but is unrelated to this issue
- Triggering the update from non-Sandbox code works fine
Workaround
So how about we conclude with a workaround ?
In some cases you could use the “after” Event Receiver rather than the “before” Event Receiver, but isn’t really a sound solution.
The best option would be to rewrite the Web Part to run its code on the client, either through Client OM (ECMAScript or Silverlight), or the SharePoint Web Services.

http://msdn.microsoft.com/en-us/library/ff798452.aspx
October 19, 2011 - 12:01, by Steven Van de Craen
Categories: SharePoint 2007, SharePoint 2010, Content TypesEver enabled Content Types on a library, removed the default “Document” Content Type and then added your own document Content Type ? If you do it in that order it will set “Folder” as the Content Type for uploaded files.
There’s no apparent way in the user interface to change the default Content Type, since “Folder” is not visible in the list:

If you don’t have a lot of lists already or you can only access SharePoint through the browser, the quickest way to fix this is to add the default “Document” Content Type to the list and immediately remove it again.
If (like in my case) you already have a lot of lists, you can script the Content Type Ordering:
using (SPSite site = new SPSite(url))
{
foreach (SPWeb web in site.AllWebs)
{
foreach (SPList list in web.GetListsOfType(SPBaseType.DocumentLibrary))
{
if (list.ContentTypes["Main Document"] != null)
{
SPFolder folder = list.RootFolder;
List<SPContentType> lstCT = new List<SPContentType>();
lstCT.Add(list.ContentTypes["Main Document"]);
folder.UniqueContentTypeOrder = lstCT;
folder.Update();
}
}
web.Close();
}
}
The above code loops all libraries on all sites in a Site Collection and sets my “Main Document” Content Type as the only (and default) Content Type. If you have different needs feel free to adapt as required.
October 17, 2011 - 21:57, by Steven Van de Craen
Categories: SharePoint 2010New APIs in SharePoint 2010 Service Pack 1 (SP1)
Funny enough a colleague pointed out to me he couldn’t find the UserProfile.ModifyProfilePicture method. Neither could I (running Service Pack 1 + June 11 CU).


Can you ? Perhaps it was removed in the June 2011 Cumulative Update ?
UPDATE (18 Oct 2011):
Had a chat with Koen Vosters on Twitter on the matter, and he verified the absence of this method in a SP1 build VM. So what happed with that method ? Was it scheduled and removed in the very end? Anyway thanks Koen for verifying !!
October 13, 2011 - 12:04, by Steven Van de Craen
Categories: General, SharePoint 2007, SharePoint 2010If you happen to change the Windows Time Zone settings AFTER Central Administration has been provisioned, you will see that the time zone/date format is not updated in the administration pages:

Luckily, the fix is quite easy. You can just update the Regional Settings of the Central Administration site. Since this option is hidden from the Site Settings, you’ll have to navigate to it manually:
http://[centraladministration/_layouts/regionalsetng.aspx

Here’s a sample of setting it to Brussels time zone and Dutch Locale:

As you can see only the Time Zone is taken into account while format is still using US Locale. This only applies for certain Administration Pages such as Search Administration. The “Timer Job Status” page for example shows the specified (Dutch) format:

September 30, 2011 - 16:31, by Steven Van de Craen
Categories: Claims, SharePoint 2010This project is further maintained at the Ventigrate Codeplex Repository (http://ventigrate.codeplex.com).
Please go there to get the latest news or for any questions regarding this topic.
Page was cross-posted to this blog on 09/30/2011.
External User Management
The External User Management solution allows for easy management of users and groups for a SharePoint 2010 environment configured for Forms Based Authentication (FBA), handled by Claims Based Authentication (CBA). It contains management pages for Site Collection Administrators to:
User Management tasks
- Add users
- Edit a user (edit details, password or role membership)
- Unlock a user
- Delete a user

Role Management tasks


Prerequisites
Log4Net is a highly flexible and configurable logging mechanism and is used by this solution. It is included in the Deployment Package and can be installed as a SharePoint Solution Package (.wsp) using STSADM or PowerShell:
STSADM -o addsolution -filename Log4Net.v1.2.10.wsp
STSADM -o deploysolution -name Log4Net.v1.2.10.wsp -allowgacdeployment -immediate
Installation
Add and deploy the SharePoint Solution Package (.wsp) using STSADM or PowerShell:
STSADM -o addsolution -filename Ventigrate.Shared.ExternalMembership.wsp
STSADM -o deploysolution -name Ventigrate.Shared.ExternalMembership.wsp -allowgacdeployment -immediate
Add an internal Alternate Access Mapping "http://extranet" for the Zone on the WebApplication that has the Membership and Role Provider (Claims) configured in it's web.config. This is the key to getting the administration pages to connect to the correct provider.

Activate the Site Collection Feature to make a link to the management pages appear in Site Collection Administration.

FAQ
Q. Will this solution work on SharePoint 2007 ?
A. No, there are certain features that make it work only in SharePoint 2010. But there are similar projects for doing FBA User Management in SharePoint 2007 on CodePlex (CKS http://cks.codeplex.com/).
Q. I don't use a Role Provider or my Membership Provider doesn't allow certain tasks such as Password Change. Can I use this ?
A. It will probably throw some issues since this code wasn't really designed to capture any possible Membership or Role Provider configuration. Feel free to provide improvements through the Discussion Boards http://ventigrate.codeplex.com/discussions.
Q. Will the Advanced Computed Field still work if I migrate from SharePoint 2007 to SharePoint 2010 ?
A. Definitely, but you'll need to upgrade the SharePoint 2007 solution package to the SharePoint 2010 version. Either retract and delete the SharePoint 2007 package prior to deploying the SharePoint 2010 package, or do an upgrade to the new solution. Make sure to IISRESET afterwards !
Q. Other questions ?
A. No problem. Ask them in the Discussion Boards http://ventigrate.codeplex.com/discussions.
Next >>