November Happy Hour will be moved to Thursday December 5th.

Lee Crowe
Feb 5, 2011
  5242
(2 votes)

PageTypeBuilder and PropertySettings Synching

Whilst creating my FilteredPageReference properties I had a thought about PageTypeBuilder and PropertySettings.

Currently PageTypeBuilder does not provide a way to synch custom property settings.

For me personally I believe having this ability may be useful as we have the ability to synch page types and property definitions so as the property settings are associated with the property definitions I decided to have a look at what could be added to PageTypeBuilder v1.3 to support this.

Using David Knipe’s post as a reference for programattically setting custom property settings I got to work Smile

The Solution

Ideally I would have liked to set the custom properties via the PageTypePropertyAttribute class like the following:

   1:  [PageTypeProperty(
   2:              EditCaption = "Filtered page reference",
   3:              Searchable = false,
   4:              Type = typeof(PropertyFilteredPageReference),
   5:              Tab = typeof(ContentTab),
   6:              SortOrder = 120,
   7:              PropertySettings = new PropertyFilteredPageReferenceSettings { StartFromCurrentPage = true, AllowQuickEdit = true, PopupHeight = 100 })]
   8:          public virtual PageReference FilteredPageReference { get; set; }

 

Unfortunately the above causes the following build exception “An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter”.

After giving this a little bit of thought I came up with the following solution.  You will see it is not ideal as some reflection is used but it works!

The Implementation

1. Firstly I modified the PageTypePropertyAttribute.cs class and added the following new properties:

   1:  public virtual string PropertySettingsCreateNewMethodName { get; set; }
   2:   
   3:  public virtual bool PropertySettingsOverwriteIfChanged { get; set; }
   4:   
   5:  public virtual bool PropertySettingsOverwriteIfChangedAndGlobal { get; set; }

Properties are described below:

  • PropertySettingsCreateNewMethodName – The name of a method within the PageType class which will return an object which implements IPropertySettings.
  • PropertySettingsOverwriteIfChanged – If true and property settings of the relevant type already exist they will be overwrote, otherwise they will be left unaltered.
  • PropertySettingsOverwriteIfChangedAndGlobal – If true and settings already exist and are global they will be overwrite, otherwise they will be left unaltered.

2. In the PageTypePropertyUpdater.cs class I modified the signature of UpdatePageDefintion to the following:

   1:  protected internal virtual void UpdatePageDefinition(PageDefinition pageDefinition, PageTypePropertyDefinition pageTypePropertyDefinition, PageTypeDefinition pageTypeDefinition)

3. In the PageTypePropertyUpdater.cs class I modified the signature of UpdatePageDefinitionValues to the following:

   1:  protected internal virtual void UpdatePageDefinitionValues(PageDefinition pageDefinition, PageTypePropertyDefinition pageTypePropertyDefinition,
   2:              PageTypeDefinition pageTypeDefinition)

4. Within the UpdatePageDefinitionValues method I added a call to the following call:

   1:  UpdatePropertySettings(pageDefinition, propertyAttribute, pageTypeDefinition);

5. Lastly I added the following new method to PageTypePropertyUpdater.cs which is responsible for updating property settings:

   1:  private void UpdatePropertySettings(PageDefinition pageDefinition, PageTypePropertyAttribute propertyAttribute,
   2:      PageTypeDefinition pageTypeDefinition)
   3:  {
   4:      if (propertyAttribute == null || string.IsNullOrEmpty(propertyAttribute.PropertySettingsCreateNewMethodName))
   5:          return;
   6:   
   7:      Type typedPageDataType = pageTypeDefinition.Type;
   8:      object typedPageDataInstance = Activator.CreateInstance(typedPageDataType);
   9:      MethodInfo createPropertySettingsMethod = typedPageDataType.GetMethod(propertyAttribute.PropertySettingsCreateNewMethodName, 
  10:          BindingFlags.Instance | BindingFlags.Public);
  11:   
  12:      if (createPropertySettingsMethod == null)
  13:          return;
  14:   
  15:      object propertySettings = createPropertySettingsMethod.Invoke(typedPageDataInstance, new object[] { });
  16:   
  17:      if (propertySettings == null || !(propertySettings is IPropertySettings))
  18:          return;
  19:   
  20:      IPropertySettingsRepository propertySettingsRepository = new PropertySettingsRepository();
  21:      PropertySettingsContainer container;
  22:   
  23:      if (pageDefinition.SettingsID == Guid.Empty)
  24:      {
  25:          pageDefinition.SettingsID = Guid.NewGuid();
  26:          pageDefinition.Save(true);
  27:          container = new PropertySettingsContainer(pageDefinition.SettingsID);
  28:      }
  29:      else if (!propertySettingsRepository.TryGetContainer(pageDefinition.SettingsID, out container))
  30:          return;
  31:   
  32:      bool isGlobal = false;
  33:      bool propertySettingsExist = true;
  34:   
  35:      PropertySettingsWrapper wrapper = container.Settings.Values
  36:          .Where(current => current.PropertySettings.GetType().Equals(propertySettings.GetType())).FirstOrDefault();
  37:   
  38:      if (wrapper == null)
  39:      {
  40:          wrapper = new PropertySettingsWrapper();
  41:          propertySettingsExist = false;
  42:      }
  43:      else
  44:          isGlobal = wrapper.IsGlobal;
  45:   
  46:      if ((propertySettingsExist && !propertyAttribute.PropertySettingsOverwriteIfChanged) ||
  47:          (propertySettingsExist && isGlobal && !propertyAttribute.PropertySettingsOverwriteIfChangedAndGlobal))
  48:      {
  49:          return;
  50:      }
  51:   
  52:      wrapper.IsGlobal = false;
  53:      wrapper.PropertySettings = propertySettings as IPropertySettings;
  54:   
  55:      if (!propertySettingsExist)
  56:          container.Settings.Add(propertySettings.GetType().FullName, wrapper);
  57:   
  58:      propertySettingsRepository.Save(container);
  59:  }

The new method above will firstly check whether a create new method has been specified and if so it will try to get it and invoke it.  The code will then create the relevant settings containers and wrappers if they need to be created and then create or overwrite settings depending on the property attribute values.

An example of setting the relevant attribute values and creating a method to create the custom property settings is below:

   1:  [PageTypeProperty(
   2:      EditCaption = "Filtered page reference",
   3:      Searchable = false,
   4:      Type = typeof(PropertyFilteredPageReference),
   5:      Tab = typeof(ContentTab),
   6:      SortOrder = 120,
   7:      PropertySettingsCreateNewMethodName = "CreateSettings",
   8:      PropertySettingsOverwriteIfChanged = true,
   9:      PropertySettingsOverwriteIfChangedAndGlobal = true)]
  10:  public virtual PageReference FilteredPageReference { get; set; }
  11:   
  12:  public PropertyFilteredPageReferenceSettings CreateSettings()
  13:  {
  14:      return new PropertyFilteredPageReferenceSettings { StartFromCurrentPage = true, AllowQuickEdit = true, PopupHeight = 100 };
  15:  }

 

Although not the cleanest solution this may be a useful way of synching page type properties and property settings on different environments!

What do people think?

Joel do you think this is something that could be useful for v2.0 of PageTypeBuilder?

Have feedback?

Please feel free to email or twitter me with any feedback @croweman

Feb 05, 2011

Comments

Joel Abrahamsson
Joel Abrahamsson Feb 6, 2011 06:32 PM

Hey Lee!
Thanks for a good post and an interesting solution.
I definitely plan to have support for property settings in the next version. Most likely the implementation will be like I described in this post: http://joelabrahamsson.com/entry/ideas-for-new-features-in-page-type-builder-20, however I will definitely look through this post a number of times when I implement it.

Please login to comment.
Latest blogs
Optimizely SaaS CMS + Coveo Search Page

Short on time but need a listing feature with filters, pagination, and sorting? Create a fully functional Coveo-powered search page driven by data...

Damian Smutek | Nov 21, 2024 | Syndicated blog

Optimizely SaaS CMS DAM Picker (Interim)

Simplify your Optimizely SaaS CMS workflow with the Interim DAM Picker Chrome extension. Seamlessly integrate your DAM system, streamlining asset...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Optimizely CMS Roadmap

Explore Optimizely CMS's latest roadmap, packed with developer-focused updates. From SaaS speed to Visual Builder enhancements, developer tooling...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Set Default Culture in Optimizely CMS 12

Take control over culture-specific operations like date and time formatting.

Tomas Hensrud Gulla | Nov 15, 2024 | Syndicated blog

I'm running Optimizely CMS on .NET 9!

It works 🎉

Tomas Hensrud Gulla | Nov 12, 2024 | Syndicated blog

Recraft's image generation with AI-Assistant for Optimizely

Recraft V3 model is outperforming all other models in the image generation space and we are happy to share: Recraft's new model is now available fo...

Luc Gosso (MVP) | Nov 8, 2024 | Syndicated blog