2

I'm using Ektron CMS version 9.0

I have smart form content which is allocated to taxonomies e.g. I might have five smart form content items (all of same) type allocated to a taxonomy, and another three to a different taxonomy:

I need to get all content of a smart form type from a taxonomy:

public IEnumerable<T> GetListOfSmartFormFromTaxonomy<T>(long taxonomyId, bool isRecursive) where T : class
{
  // TODO
}

What I have working, based on links below, is this:

public IEnumerable<TaxonomyItemData> GetListOfSmartFormFromTaxonomy(long taxonomyId)
{
    TaxonomyItemCriteria criteria = new TaxonomyItemCriteria();
    criteria.AddFilter(TaxonomyItemProperty.TaxonomyId, CriteriaFilterOperator.EqualTo, taxonomyId);

    TaxonomyItemManager taxonomyItemManager = new TaxonomyItemManager();
    List<TaxonomyItemData> taxonomyItemList = taxonomyItemManager.GetList(criteria);

    return taxonomyItemList;
}

But this just gets the item's titles and ids, not the smart form data itself.

As an Ektron newbie, I don't know how to get all the items of one Smart Form type using only one call (instead of looping through each item and fetching it by ID which is not efficient)

What have I missed? I am working on this actively today and will post my findings here.

References used so far:

EDIT

Posted my just-got-it-working solution below as an fyi and awarded closest answer as accepted. Thanks everyone for your help. Please chime in with any improvements ;)

Community
  • 1
  • 1
Ruskin
  • 5,721
  • 4
  • 45
  • 62
  • Just found this ... may be the answer: http://reference.ektron.com/developer/framework/content/contentmanager/getlistByTaxonomy.aspx – Ruskin Mar 24 '14 at 12:46
  • That's exactly right - you want to use the ContentTaxonomyCriteria and the ContentManager. The TaxonomyItem objects and managers are more like getting the properties for the relationship between content and taxonomy. – egandalf Mar 24 '14 at 12:59
  • If you are interested, the use-case is FAQ. Many individual questions that can be in one or more taxonomies, pulled into a widget based on taxonomy and ordered by title - so can have a FAQ widget of General, All etc. – Ruskin Mar 24 '14 at 13:09
  • Note 2, also posted to twitter with tag #ektron (having read about it on this post: http://stackoverflow.com/questions/10747792/what-is-the-best-online-site-to-post-questions-on-ektron/10756114#10756114 ) - I would recommend this approach to others - egandalf replied almost at once TQ ;) – Ruskin Mar 24 '14 at 13:14
  • One thought based on your code - since the framework api returns a List, it might be misleading to return IEnumerable from your method. Your result is List, and returning IEnumerable might give the impression that it hasn't yet been enumerated. There's a good discussion of one such implication here: http://stackoverflow.com/questions/7969354/count-property-vs-count-method – Brian Oliver Mar 24 '14 at 14:21

3 Answers3

6

I'd recommend using the ContentTaxonomyCriteria with the ContentManager.

long smartFormId = 42;
long taxonomyId = 127;
bool isRecursive = true;

var cm = new ContentManager();

var taxonomyCriteria = new ContentTaxonomyCriteria();
taxonomyCriteria.AddFilter(ContentProperty.XmlConfigurationId, CriteriaFilterOperator.EqualTo, smartFormId);
taxonomyCriteria.AddFilter(taxonomyId, isRecursive);

var content = cm.GetList(taxonomyCriteria);

UPDATE

The ContentData object has a property called XmlConfiguration. When the content is based on a smartform, this property will be non-null and have a positive (non-zero) Id: content[0].XmlConfiguration.Id for example.

I often add an Extension Method to my code that will tell me whether a given ContentData is based on a smart form:

public static class ContentDataExtensions
{
    public static bool IsSmartFormContent(this ContentData content)
    {
        return content != null && content.XmlConfiguration != null && content.XmlConfiguration.Id > 0;
    }
}

That way I can take a content (or list of content) and check it very quickly in code to see if it's based on a smartform or not:

foreach (var contentData in contentList)
{
    if (contentData.IsSmartFormContent())
    {
        // Do smart-form stuff here...
    }
}

Of course, if your content is coming from the framework api and you used a criteria object that is selecting based on a specific XmlConfigurationId, then in theory you wouldn't have to use that, but it still comes in handy quite often.

Brian Oliver
  • 1,407
  • 2
  • 15
  • 25
  • I have not played with ContentProperty.XmlConfigurationId yet ... does that filter the output by smart form type? ... quickly looks up how to get an smart-form type id from c# type or name ... – Ruskin Mar 24 '14 at 13:28
  • Yes, XmlConfigurationId is the same as the smart form id of the content block. I've updated my answer to give more details. – Brian Oliver Mar 24 '14 at 13:38
  • How can I remove metadata entry from a content created with smartform using c#? – Si8 Dec 15 '15 at 14:30
3

I'm not quite sure I understand your organizational structure, but you do have the ability to do your own sub clauses that select directly against the database.

In this case I wouldn't use the TaxonomyItemManager, I would use the ContentManager with a special criteria:

ContentManager cApi = new ContentManager();
var criteria = new ContentCriteria();
criteria.AddFilter(ContentProperty.Id, CriteriaFilterOperator.InSubClause, "select taxonomy_item_id where taxonomy_id = " + taxonomyId);
criteria.AddFilter(ContentProperty.XmlConfigurationId, CriteriaFilterOperator.EqualTo, smartformTypeId);
var yourContent = cApi.GetList(criteria);

That should do what you're asking for (grab the content specifically that is a member of a Taxonomy while only being of a specific SmartForm config). It's worth noting you don't need the second criteria piece (XmlConfigurationId) if your Taxonomy only contains that XmlConfiguration.

  • 1
    You can use code similar to this, but with the ContentTaxonomyCriteria which allows you to mix taxonomy id and content properties in a single criteria & request. Don't use the TaxonomyItemManager at all. – egandalf Mar 24 '14 at 13:00
  • You can tell I don't use Taxonomy that often. Thanks! – MiracleManS Mar 24 '14 at 13:04
  • Thanks @MiracleManS ... nearly got it working. I'll post the working solution when I see it. +1 for your hint. – Ruskin Mar 24 '14 at 13:08
0

For Information, this is what I came up with. Noted Brian Oliver's comment on List but using patterns from other devs, can refactor later.

To clarify, we are creating classes from the XSDs generated from the smart forms, so have smart form types to play with. Your use may be simpler that ours.

public IEnumerable<T> GetListOfSmartFormFromTaxonomy<T>(long taxonomyId, bool isRecursive = false) where T : class
{
    long smartFormId = GetSmartFormIdFromType(typeof(T));
    // checks here for smartformid=0

    ContentManager contentManager = new ContentManager();
    ContentTaxonomyCriteria criteria = new ContentTaxonomyCriteria();

    // Smart Form Type
    criteria.AddFilter(ContentProperty.XmlConfigurationId, CriteriaFilterOperator.EqualTo, smartFormId);

    // Taxonomy
    criteria.AddFilter(taxonomyId, isRecursive);

    List<ContentData> contentDataList = contentManager.GetList(criteria);
    IEnumerable<T> smartFormList = ConvertToSmartFormList<T>(pressReleaseDataList);

    return smartFormList;
}

private IEnumerable<T> ConvertToSmartFormList<T>(List<ContentData> contentDataList) where T : class
{
    List<T> smartFormList = new List<T>();
    if (contentDataList != null && contentDataList.Count > 0)
    {
        foreach (ContentData contentData in contentDataList)
        {
            if (contentData.IsSmartFormContent())
            {
                T smartForm = GetDeserializedContent<T>(contentData.Html);
                if (smartForm != null)
                {
                    PropertyInfo property = smartForm.GetType().GetProperty("ContentId");
                    if (property != null)
                    {
                        property.SetValue(smartForm, contentData.Id, null);
                    }

                    smartFormList.Add(smartForm);
                }
            }
        }
    }

    return smartFormList;
}

private long GetSmartFormIdFromType(Type smartFormType)
{
    SmartFormConfigurationManager manager = new SmartFormConfigurationManager();
    SmartFormConfigurationCriteria criteria = new SmartFormConfigurationCriteria();

    // Note: Smart Form Title must match the type's name, i.e. no spaces, for this to work
    criteria.AddFilter(SmartFormConfigurationProperty.Title, CriteriaFilterOperator.EqualTo, smartFormType.Name);

    List<SmartFormConfigurationData> configurationData = manager.GetList(criteria);

    if (configurationData == null || configurationData.Count == 0)
    {
        return 0;
    }

    return configurationData.First().Id;
}
Ruskin
  • 5,721
  • 4
  • 45
  • 62