More in this section

Forums / Developing with Sitefinity / Custom meta field population

Custom meta field population

9 posts, 1 answered
  1. Andree
    Andree avatar
    44 posts
    Registered:
    11 Jan 2010
    24 Mar 2010
    Link to this post
    Hi Ivan,

    Today I have tried expanding one of my custom Generic Content modules by adding two new meta fields onto the content properties:

    <add key="Articles.OnlyJapanese" valueType="Boolean" visible="True" searchable="False" sortable="True" defaultValue="False" />
    <add key="Articles.OnlyEnglish" valueType="Boolean" visible="True" searchable="False" sortable="True" defaultValue="False" />

    The idea is that by default, all content is displayed in my custom frontend control, but it also has the ability to exclude japanese-only content, and English-only content. It does this in my CreateCustomFilter() method, by the way of the following code:

    if (ExcludeEnglish)
       builder.AddFilter(new ContentFilterStatement("OnlyEnglish", "True", ContentFilter.Condition.NotEqual, ContentFilter.JoinType.And));
      
    if (ExcludeJapanese)
       builder.AddFilter(new ContentFilterStatement("OnlyJapanese", "True", ContentFilter.Condition.NotEqual, ContentFilter.JoinType.And));

    Now my problem comes when displaying content where the OnlyEnglish and OnlyJapanese meta fields have not been saved, as they are new properties. If the ContentFilterBuilder finds a Generic Content item without the property, it excludes it from the results altogether.

    In order to ensure that every single content item has these meta fields, I need to go through each one individually and save it again, to make sure the Meta field values get saved out to database.

    Is there a way to speed up this process? There are several hundred generic content items to do, which is quite a time consuming exercise.


    Regards,
    Alvaro
  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    24 Mar 2010
    Link to this post
    Hello Alvaro,

    The metakleys could be localized as well if you set localizable property to true

    <add key="SomeProvider.Field" 
     localizable="True" 
     valueType="ShortText" 
     visible="True" 
     searchable="True" 
     sortable="True" 
     defaultValue="" />

    You can get each content depending on the culture and loop through metakeys collection and save each key programmatically

    // set a culture, so that the manage will pick up all content items from this language
    System.Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.GetCultureInfo("en");

    foreach (IMetaInfo info in this.Manager.MetaKeys.Values)
            {
     
                bool found = false;
     
                 if (info.Key == "Name" || info.Key == "Title")
                 {
                      ....
                           ....
     
                         cnt.SetMetaData(info.Key, txt.Text);
                     found = true;
                 }
     
                 if (found)
                     break;
            }
     
             this.Manager.SaveContent(cnt);


    Greetings,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  3. Andree
    Andree avatar
    44 posts
    Registered:
    11 Jan 2010
    01 Apr 2010
    Link to this post
    Hi Ivan,

    I have adapted your code slightly to the following:

    ContentManager manager = new ContentManager("Articles");
    System.Collections.IList content = manager.GetContent();
    foreach (IContent item in content)
    {
        bool AnyChange = false;
        if (item.GetMetaData("OnlyJapanese") == null)
        {
            item.SetMetaData("OnlyJapanese", false);
            AnyChange = true;
        }
        if (item.GetMetaData("OnlyEnglish") == null)
        {
            item.SetMetaData("OnlyEnglish", false);
            AnyChange = true;
        }
        if (AnyChange)
            manager.SaveContent(item, ContentStatus.Published);
    }

    This is intended as a bit of code to be executed once on the server, to ensure that every GenericContent item under my Articles module has the meta data set.

    However, even after calling the SaveContent() method, next time I run the code, the same old content with the missing MetaData still has the MetaData of OnlyJapanese and OnlyEnglish missing.

    Should I be using another method for saving out the MetaData?


    Regards,
    Alvaro
  4. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    01 Apr 2010
    Link to this post
    Hello Alvaro,

    I am not having any problems with the similar code

    var Manager = new ContentManager("Some_Module");
          var allContentItems = Manager.GetContent();
          if (allContentItems.Count > 0)
          {
              foreach (IContent cnt in allContentItems)
              {
                  var val = cnt.GetMetaData("SetValue");
                  if (val == null)
                  {
                      cnt.SetMetaData("SetValue", false);
                      Manager.SaveContent(cnt);
                      var updatedValue = cnt.GetMetaData("SetValue");
                  }
              }
          }

    After calling Manager.SaveContent method you could get the metadata again to see whether it has been saved ( the highlighted line)

    Greetings,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  5. Andree
    Andree avatar
    44 posts
    Registered:
    11 Jan 2010
    01 Apr 2010
    Link to this post
    Hi Ivan,

    I have followed your advice and the item.GetMetaData("KeyValue") does return content after calling the SaveContent() method, as shown in the screenshot below:

    http://www.haushinka.org/media/firstrun.jpg

    The problem is that whilst the class is returning the correct value once it's been modified, it's not persisting it to database. When I run the same code again, I get the following:

    http://www.haushinka.org/media/secondrun.jpg

    The GenericContent item whose MetaData had been set, now has a value of NULL again.

    Looking at SQL Server Profiler, I can't see any database operations persisting this new MetaData content to database, so it would further point to the SaveContent() method not actually persisting the new MetaData changes.

    Any ideas?


    Regards,
    Alvaro
  6. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    02 Apr 2010
    Link to this post
    Hello Alvaro,

    The problem is that whilst the class is returning the correct value once it's been modified, it's not persisting it to database.

    Form where do you modify the item? Through UI or programmatically. If you do it through UI does the control that gets/sets it returns the correct value in Edit mode of the item? Check also whether the controls that get/set the value are added inside ContentMetaFields control. If the control is outside ContentMetaFileds control the values will not be persisted. If you are manipulating all this programmatically and you lost the value, the problem is somewhere in the code logic you have.

    Greetings,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
  7. Andree
    Andree avatar
    44 posts
    Registered:
    11 Jan 2010
    02 Apr 2010
    Link to this post
    Hi Ivan,

    It isn't a single item that I wish to modify - it's every single content item within my custom module. The idea behind this is that I need to set the default values of OnlyJapanese and OnlyEnglish to "False". To achieve this, I have created a custom control whose codebehind looks like this:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
      
    using Telerik.Cms.Engine;
    using Telerik.Cms.Engine.Data;
    using Telerik.Cms.Engine.Security;
    using Telerik.Security.Permissions;
      
    public partial class Sitefinity_UserControls_Eularis_KCFix : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            ContentManager manager = new ContentManager("Articles");
      
            System.Collections.IList content = manager.GetContent();
      
            string Key1 = "OnlyJapanese";
            string Key2 = "OnlyEnglish";
      
            foreach (IContent item in content)
            {
                var m = item.GetMetaData(Key1);
                if (m == null)
                {
                    item.SetMetaData(Key1, false);
                    manager.SaveContent(item, ContentStatus.Published);
                    var n = item.GetMetaData(Key1);
                }
      
                var m2 = item.GetMetaData(Key2);
                if (m2 == null)
                {
                    item.SetMetaData(Key2, false);
                    manager.SaveContent(item, ContentStatus.Published);
                    var n2 = item.GetMetaData(Key2);
                }
            }
        }
    }

    The idea behind this control is that it gets added to a rough page on the site, then when the page is loaded for the first time, all of the values will finally be set on the site. From there, I can remove the control and page completely - it is a "one time" execution of code.

    The only code logic I have used is shown above, there is no other code logic involved in this exercise.


    Regards,
    Alvaro
  8. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    02 Apr 2010
    Link to this post
    Hi Alvaro,

    You have to get the content in transaction before modify it.

    var manager = new ContentManager("NAME OF YOUR PROVIDER");
    var content = manager.GetContent();
     
    int count = content.Count;
     
    string Key1 = "OnlyJapanese";
    string Key2 = "OnlyEnglish";
     
    foreach (IContent item in content)
    {
     
        var modifyObj = manager.GetCurrentState(item.ID);
        var oj = (bool)item.GetMetaData(Key1);
        if (oj == null)
        {
            item.SetMetaData(Key1, false);
            manager.SaveContent(item);
            var ojResult = item.GetMetaData(Key1);
        }
     
        var modifyObj2 = manager.GetCurrentState(item.ID);
        var oe = (bool)item.GetMetaData(Key2);
        if (oe == null)
        {
            item.SetMetaData(Key2, false);
            manager.SaveContent(item);
            var oeResult = item.GetMetaData(Key2);
        }
    }


    Greetings,
    Ivan Dimitrov
    the Telerik team

    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items.
    Answered
  9. Andree
    Andree avatar
    44 posts
    Registered:
    11 Jan 2010
    03 Apr 2010
    Link to this post
    Excellent, that's done it - my fix is in place now.

    Many thanks Ivan!


    Regards,
    Alvaro
Register for webinar
9 posts, 1 answered