Second Life of a Hungarian SharePoint Geek

October 21, 2011

How to deploy a custom field with custom properties from a feature – the missing second part

Filed under: Custom fields, Deployment, Features, PowerShell, SP 2010 — Tags: , , , , — Peter Holpar @ 14:49

Only readers following my blog from the beginning may remember my post I wrote about the deployment of custom fields having custom properties more than three years ago. Of course that post is about WSS 3.0.

At that time I described how to include the custom properties into the field definition even if these properties are not declared by the XSD validation schema. However, injecting the custom properties the way I described there did not have effect on the values of the custom properties the custom field actually deployed with. I promised then that in the next part I would show you how to resolve this issue. It’s better late than never, the second part comes now, updated for SharePoint 2010.

The trick to achieve our goal seemed originally to be really simple. The base idea behind  it was that an instance of the field must be created sooner or later before usage, and the values we would like to push into the custom properties were available on object creation in the field schema deployed.

I’ve modified the constructors of the custom field, adding a call to my custom InitializeProps method.

  1. public SPFieldRegEx(SPFieldCollection fields, string fieldName)
  2.     : base(fields, fieldName)
  3. {
  4.     InitializeProps();
  5. }
  6.  
  7. public SPFieldRegEx(SPFieldCollection fields, string typeName, string displayName)
  8.     : base(fields, typeName, displayName)
  9. {
  10.     InitializeProps();
  11. }

The InitializeProps method is responsible for reading up the deployed custom property values from the field schema and setting them to the standard custom location in the schema.

  1. // in the custom field feature definition
  2. private readonly string customNamespaceUri = "http://schemas.grepton.com/sharepoint/";
  3.  
  4. private void InitializeProps()
  5. {
  6.     String regEx = (String)GetCustomProperty("RegEx");
  7.  
  8.     // value of custom property is null if not yet set
  9.     if (regEx == null)
  10.     {
  11.  
  12.         // load the field schema into an XML document
  13.         XmlDocument schemaXml = new XmlDocument();
  14.         schemaXml.LoadXml(SchemaXml);
  15.  
  16.         XmlNode fieldNode = schemaXml.SelectSingleNode("Field");
  17.  
  18.         if (fieldNode != null)
  19.         {
  20.             InitCustomProperty(fieldNode, "RegEx");
  21.             InitCustomProperty(fieldNode, "ErrMsg");
  22.             InitCustomProperty(fieldNode, "MaxLen");
  23.         }
  24.  
  25.     }
  26.  
  27. }
  28.  
  29. private void InitCustomProperty(XmlNode fieldNode, String custPropName)
  30. {
  31.     XmlAttribute custPropOrigAttr = fieldNode.Attributes[custPropName, customNamespaceUri];
  32.     // should not be null, but we check it
  33.     if (custPropOrigAttr != null)
  34.     {
  35.         SetCustomProperty(custPropName, custPropOrigAttr.Value);
  36.     }
  37. }

After deploying my custom field, I’ve checked my field at the Change Site Column page and was happy to see my custom property values there:

image

However, it turned out quickly that the schema of my field was not updated as expected:

  1. <Field
  2.   ID="{54634385-A8AC-4898-BF24-E533EB23444F}"
  3.   Name="RegExField"
  4.   DisplayName="RegExField"
  5.   StaticName="RegExField"
  6.   Group="Grepton Fields"
  7.   Type="SPFieldRegEx"
  8.   Sealed="FALSE"
  9.   AllowDeletion="TRUE"
  10.   SourceID="http://schemas.microsoft.com/sharepoint/v3/fields"
  11.   Description="This is the RegEx field"
  12.   grp:RegEx="[0-9]"
  13.   grp:MaxLen="20"
  14.   grp:ErrMsg="Error!"
  15.   xmlns:grp="http://schemas.grepton.com/sharepoint/" />

Of course, pressing OK on the Change Site Column page updated the field schema with the custom properties:

  1. <Field
  2.   ID="{54634385-A8AC-4898-BF24-E533EB23444F}"
  3.   Name="RegExField"
  4.   DisplayName="RegExField"
  5.   StaticName="RegExField"
  6.   Group="Grepton Fields"
  7.   Type="SPFieldRegEx"
  8.   Sealed="FALSE"
  9.   AllowDeletion="TRUE"
  10.   SourceID="http://schemas.microsoft.com/sharepoint/v3/fields"
  11.   Description="This is the RegEx field"
  12.   grp:RegEx="[0-9]"
  13.   grp:MaxLen="20"
  14.   grp:ErrMsg="Error!"
  15.   xmlns:grp="http://schemas.grepton.com/sharepoint/"
  16.   Required="FALSE"
  17.   EnforceUniqueValues="FALSE"
  18.   Version="1">
  19.   <Customization>
  20.     <ArrayOfProperty>
  21.       <Property>
  22.         <Name>RegEx</Name>
  23.         <Value
  24.           xmlns:q1="http://www.w3.org/2001/XMLSchema"
  25.           p4:type="q1:string"
  26.           xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">[0-9]</Value>
  27.       </Property>
  28.       <Property>
  29.         <Name>MaxLen</Name>
  30.         <Value
  31.           xmlns:q2="http://www.w3.org/2001/XMLSchema"
  32.           p4:type="q2:double"
  33.           xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">20</Value>
  34.       </Property>
  35.       <Property>
  36.         <Name>ErrMsg</Name>
  37.         <Value
  38.           xmlns:q3="http://www.w3.org/2001/XMLSchema"
  39.           p4:type="q3:string"
  40.           xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">Error!</Value>
  41.       </Property>
  42.     </ArrayOfProperty>
  43.   </Customization>
  44. </Field>

That gave me the idea that I should try to deploy my custom field using this schema. I removed my custom attributes from the Field element and used the following XML to deploy the field.

  1. <?xml version="1.0" encoding="utf-8" ?>
  2. <Elements xmlns="http://schemas.microsoft.com/sharepoint/">
  3.   <Field
  4.     ID="{54634385-A8AC-4898-BF24-E533EB23444F}"
  5.     Name="RegExField"
  6.     DisplayName="RegExField"
  7.     StaticName="RegExField"
  8.     Group="Grepton Fields"
  9.     Type="SPFieldRegEx"
  10.     Sealed="FALSE"
  11.     AllowDeletion="TRUE"
  12.     SourceID="http://schemas.microsoft.com/sharepoint/v3/fields"
  13.     Description="This is the RegEx field"
  14.     Version="1">
  15.     <Customization>
  16.       <ArrayOfProperty>
  17.         <Property>
  18.           <Name>RegEx</Name>
  19.           <Value
  20.             xmlns:q1="http://www.w3.org/2001/XMLSchema"
  21.             p4:type="q1:string"
  22.             xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">[0-9]</Value>
  23.         </Property>
  24.         <Property>
  25.           <Name>MaxLen</Name>
  26.           <Value
  27.             xmlns:q2="http://www.w3.org/2001/XMLSchema"
  28.             p4:type="q2:double"
  29.             xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">20</Value>
  30.         </Property>
  31.         <Property>
  32.           <Name>ErrMsg</Name>
  33.           <Value
  34.             xmlns:q3="http://www.w3.org/2001/XMLSchema"
  35.             p4:type="q3:string"
  36.             xmlns:p4="http://www.w3.org/2001/XMLSchema-instance">Error!</Value>
  37.         </Property>
  38.       </ArrayOfProperty>
  39.     </Customization>
  40.   </Field>
  41. </Elements>

I’ve removed my custom codes described above either, and tried to deploy the field.

Voilà! The field is deployed successfully, including the custom properties. At that point I really don’t understand if it would work for WSS 3.0 and if so, how I missed to find that solution three years ago. The main point it is working now and requires no hacking at all.

A mystical observation is that after deploying the field I was not able to get a reference for the new field using PowerShell:

$avFields = $web.AvailableFields
$avFields["RegExField"]

At the same time, the field is visible on the web UI, and the following C# code finds it:

SPFieldCollection avFields = web.AvailableFields;
SPField field = avFields["RegExField"];

If I create the field from code, PowerShell finds that either:

SPFieldCollection fields = web.Fields;
SPField fieldCode = new SPField(fields, "SPFieldRegEx", "RegExCode");
fields.Add(fieldCode);

If you know the reason for that, let me know, please!

About these ads

1 Comment »

  1. Thanks a ton! That solution worked great. You’ve saved me from a lot of SharePoint agony.

    Comment by Matt — February 10, 2012 @ 23:01


RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

The Shocking Blue Green Theme. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.

Join 54 other followers

%d bloggers like this: