Query library items by tag

Posted by Community Admin on 03-Aug-2018 15:12

Query library items by tag

All Replies

Posted by Community Admin on 18-Feb-2011 00:00

Hi all,

I want to query some items from an image library.
I have this code:

var images = App.WorkWith().Images().Where((w) => w.Album.Title == "Visuals" &&
                   w.Status == Telerik.Sitefinity.GenericContent.Model.ContentLifecycleStatus.Live).Get();

... which works.

Now I'd like to get only images that are having a specific Tag.
I want to do something like this, but that isn't allowed, because an Library.Model.Image cannot be cast to a ContenItem.

List<Telerik.Sitefinity.Libraries.Model.Image> filteredImages = new List<Telerik.Sitefinity.Libraries.Model.Image>();
foreach (Telerik.Sitefinity.Libraries.Model.Image item in images)
   ContentItem i = item as ContentItem;
   if (i.TagsText.IndexOf("Visual") > -1)
      filteredImages.Add(item);

An Image doesn't have the TagsText as property.
How should I do this?

Regards,
Daniel

Posted by Community Admin on 18-Feb-2011 00:00

Hi Daniel,

Please take a look at this post.

Regards,
Ivan Dimitrov
the Telerik team

Posted by Community Admin on 18-Feb-2011 00:00

Hi Ivan,

Thanks for the help.
I don't know the GUID of the Taxon.

I have to do it by name/title.

Regards,
Daniel

Posted by Community Admin on 18-Feb-2011 00:00

Hello Daniel,

Use TaxonomyManager to get the taxon and then its ID.

Best wishes,
Ivan Dimitrov
the Telerik team

Posted by Community Admin on 28-Feb-2011 00:00

Thanks that worked.

Posted by Community Admin on 15-Mar-2011 00:00

Here is the completed code for convenience:

public partial class Test : System.Web.UI.Page
    protected void Page_Load(object sender, EventArgs e)
    
        var taxonomyManager = TaxonomyManager.GetManager();
 
        var taxon = taxonomyManager.GetTaxa<FlatTaxon>().Where(t => t.Name == "tag1").Single();
 
        string itemTypeName = "Telerik.Sitefinity.Libraries.Model.Image";
        Type itemType = TypeResolutionService.ResolveType(itemTypeName);
        var manager = ManagerBase.GetMappedManager(itemType, "");
 
        ContentDataProviderBase contentProvider = manager.Provider as ContentDataProviderBase;
        var items = GetItems(taxon, contentProvider, itemType);
 
        foreach (Telerik.Sitefinity.Libraries.Model.Image item in items)
        
            Response.Write("ID: " + item.Id + "<br />");
            Response.Write("Url Name: " + item.UrlName + "<br />");
        
    
 
    private IEnumerable GetItems(ITaxon taxon, ContentDataProviderBase contentProvider, Type itemType)
    
        TaxonomyPropertyDescriptor prop = GetPropertyDescriptor(itemType, taxon);
        int? totalCount = 0;
        var filter = "Status = Master";
        var items = contentProvider.GetItemsByTaxon(taxon.Id, prop.MetaField.IsSingleTaxon, prop.Name, itemType, filter, string.Empty, 0, 100, ref totalCount);
        return items;
    
 
    private TaxonomyPropertyDescriptor GetPropertyDescriptor(Type itemType, ITaxon taxon)
    
        return TaxonomyManager.GetPropertyDescriptor(itemType, taxon);
    

Can't this be done with one line of Fluent API?

Posted by Community Admin on 18-Mar-2011 00:00

Hello Basem,

There is a way through the fluent API, but again you should know the category/tag ID

var categID = newGuid("");

var content = App.WorkWith().NewsItems().Where(ci => ((IList<Guid>)ci.GetValue("Category")).Contains(categID));



All the best,
Ivan Dimitrov
the Telerik team

Posted by Community Admin on 06-May-2011 00:00

Hello,

Does there exist a best practice for getting items by more than one Taxon.  I'm filtering NewsItems by Category and Tag.  I've been able to get a collection filtered by Category and another collection filtered by Tag and taking the intersection to get the result I want.  

Thanks!

Michael

Posted by Community Admin on 09-May-2011 00:00

Hi ,

You can add logical operands to the LINQ condition.

Best wishes,
Ivan Dimitrov
the Telerik team

Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 09-May-2011 00:00

Thanks for the reply Ivan.

I'm not sure how I could apply logical operands here.  Here's how I got this to "work".  I know there's got to be a better way.  

#region News
        
            List<NewsItem> cItemsCatFilter = new List<NewsItem>();
            List<NewsItem> cItemsTagFilter = new List<NewsItem>();
            // Get Category Taxon
            HierarchicalTaxon taxonCat = _resourceCats.SingleOrDefault(rc => rc.Title.ToLower() == "news");
             
            // Get Items
            string itemTypeName = "Telerik.Sitefinity.News.Model.NewsItem";
            Type itemType = TypeResolutionService.ResolveType(itemTypeName);
            IManager manager = ManagerBase.GetMappedManager(itemType, "");
            ContentDataProviderBase contentProvider = manager.Provider as ContentDataProviderBase;
            // Get collection filter by Category
            IEnumerable n1 = GetItems(taxonCat, contentProvider, itemType);
            cItemsCatFilter.AddRange(n1.OfType<NewsItem>());
            // Get collection filter by Tag
            IEnumerable n2 = GetItems(_tagTaxon, contentProvider, itemType);
            cItemsTagFilter.AddRange(n2.OfType<NewsItem>());
            // Filter by Tags and LifeCycle
            var items = cItemsCatFilter.Intersect<NewsItem>(cItemsTagFilter, new Utility.NewsItemComparer())
                                        .Where(ci => ci.Status != ContentLifecycleStatus.Live)
                                        .OrderBy(ci => ci.PublicationDate)
                                        .Take(5)
                                        .ToList();
 
            if (items.Count != 0)
            
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < items.Count; i++)
                
                    // Create link with Title
                    sb.AppendLine("<p>" + items[i].Title + "</p>");
                    sb.AppendLine("<div style='height: 1px; background-color: #E2EBE9; margin: 5px 0;'></div>");
                
                 //add More Link
                sb.AppendLine("<a href='#' style='color: Black;'><p>More News »</p></a>");
                ltlNews.Text = sb.ToString();
            
            else
            
                phNews.Visible = false;
            
       
  #endregion

Thanks!

Michael



Posted by Community Admin on 12-May-2011 00:00

Hello,

You need to use the query as shown below

var categID = newGuid("generate a guid here");
var categID1 = newGuid("generate a guid here");                
 
var content = App.WorkWith().ContentItem().Where(ci => ((IList<Guid>)ci.GetValue("Category")).Contains(categID) && ((IList<Guid>)ci.GetValue("Category")).Contains(categID1));


Kind regards,
Ivan Dimitrov
the Telerik team
Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 12-May-2011 00:00

Hello,

This doesn't work for filtering by TAG (taxonomy [nme] = 'Tags').  The News object does not have a property TagsText.

Thanks!

Michael

Posted by Community Admin on 16-May-2011 00:00

Hi Michael,

The objects contain only a refence to the ID of the tag. You have to first get the Tag's ID using the taxonomy manager, then use Ivan's approach for filtering.

Kind regards,
Radoslav Georgiev
the Telerik team

Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 24-May-2011 00:00

Hello,

I stumbled upon the solution below after considering writing my own sprocs to get this data.  
In using GetValue(this IDynamicFieldsContainer dataItem, string fieldName), I'm wondering where I can find all of the "fieldName" options.  

Get News items by Tag:

var items = App.WorkWith().NewsItems().Where(ci => ((IList<Guid>)ci.GetValue("Tags")).Contains(tagTaxonID))
                           .Get();

Get News Items by Category:
var items = App.WorkWith().NewsItems()
                                    .Where(ci => ((IList<Guid>)ci.GetValue("Category")).Contains(taxonCatID)).Get();

My Example creating a list of NewsItems filltering by Category and Tag
items = App.WorkWith().NewsItems()
                                    .Where(ci => ((IList<Guid>)ci.GetValue("Tags")).Contains(tagTaxonID))
                                    .Where(ci => ((IList<Guid>)ci.GetValue("Category")).Contains(taxonCatID))
                                    .Get()
                                    .Where(ci => ci.Status == ContentLifecycleStatus.Live)
                                    .OrderByDescending(ci => ci.PublicationDate)
                                    .ToList();

Thanks!

Michael

Posted by Community Admin on 10-Aug-2011 00:00

The Fluent API method doesn't work with ContentItems, just with NewsItem and probably other built in modules. It seems ContentItems is too generic for it. This is the error I get:

Database mapped field does not exist.
Parameter name: methodCallExpression
Actual value was ci.FieldValue("Category").

Stack Trace:

[ArgumentOutOfRangeException: Database mapped field does not exist.
Parameter name: methodCallExpression
Actual value was ci.FieldValue("Category").]
   Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQueryImpl(Type type, Int32 elementAt, Object[] groupResolutionParamValues, Boolean single, Boolean checkOid) +736
   Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQuery(Type type, Int32 elementAt, Object[] groupResolutionParamValues, Boolean single, Boolean checkOid) +55

[InvalidOperationException: An exception occured during the execution of '
Extent<Telerik.Sitefinity.GenericContent.Model.ContentItem>.Where(item => (item.ApplicationName == value(Telerik.Sitefinity.Modules.GenericContent.Data.OpenAccessContentProvider+<>c__DisplayClass0).appName)).Where(ci => (ci.FieldValue("Category").Any(item => item.Equals(value(Telerik.Sitefinity.Data.Linq.OpenAccess.OpenAccessExpressionVisitor`2+<>c__DisplayClassa[Telerik.Sitefinity.GenericContent.Model.ContentItem,Telerik.Sitefinity.GenericContent.Model.ContentItem]).comparingObject)) AndAlso (Convert(Convert(Convert(ci.Status))) == 2)))'. See InnerException for more details.
]
   Telerik.OpenAccess.Query.ExpressionCompiler.PerformDatabaseQuery(Type type, Int32 elementAt, Object[] groupResolutionParamValues, Boolean single, Boolean checkOid) +244
   Telerik.OpenAccess.Query.ExpressionExecution.PerformDatabaseQuery(Piece`1 piece, Object[] grpVals) +444
   Telerik.OpenAccess.Query.Piece`1.System.Collections.Generic.IEnumerable<T>.GetEnumerator() +37
   Telerik.Sitefinity.Data.Linq.LinqQuery`2.GetEnumerator() +83
   System.Collections.Generic.List`1..ctor(IEnumerable`1 collection) +315
   System.Linq.Enumerable.ToList(IEnumerable`1 source) +58
   SitefinityWebApp.Custom.Categories.BuildCategory(String name) in C:\Data\IIS\...\Categories.ascx.cs:105
   SitefinityWebApp.Custom.Categories.Page_Load(Object sender, EventArgs e) in C:\Data\IIS\...\Categories.ascx.cs:67
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +14
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +35
   System.Web.UI.Control.OnLoad(EventArgs e) +91
   System.Web.UI.Control.LoadRecursive() +74
   System.Web.UI.Control.LoadRecursive() +146
   System.Web.UI.Control.LoadRecursive() +146
   System.Web.UI.Control.LoadRecursive() +146
   System.Web.UI.Control.LoadRecursive() +146
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +2207

Posted by Community Admin on 10-Aug-2011 00:00

Hi Basem,

Generic Content (now Shared Content) ContentItem type does not have Category field, nor Tags fields. Probably this is causing your problems.

Regards,
Radoslav Georgiev
the Telerik team

Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 10-Aug-2011 00:00

I was actually trying to do this for the custom Products Module. I was thinking ContentItem was the base class, but you refreshed my memory it is Content that is the base class. For a custom type like Products, it seems the Fluent API is not an option?

Posted by Community Admin on 10-Aug-2011 00:00

Hi Basem,

You can try working with the App.WorkWith().AnyContentItem<T>  facade if you want to use fluent API for custom modules. There you can pass the type of your custom class and work with it.

Greetings,
Radoslav Georgiev
the Telerik team

Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

Posted by Community Admin on 10-Aug-2011 00:00

Looks like this is only for retrieving a single item because there is no "where" clause. "AnyContentItems" (plural) would be sweet but doesn't exist

Posted by Community Admin on 10-Aug-2011 00:00

This is what I ended up doing for reference:

public IEnumerable GetItems(ITaxon taxon)
    string itemTypeName = typeof(ProductItem).FullName;
    Type itemType = TypeResolutionService.ResolveType(itemTypeName);
    var manager = ManagerBase.GetMappedManager(itemType, "");
    ContentDataProviderBase contentProvider = manager.Provider as ContentDataProviderBase;
    TaxonomyPropertyDescriptor prop = TaxonomyManager.GetPropertyDescriptor(itemType, taxon);
    int? totalCount = 0;
    var filter = "Status = Master";
    var items = contentProvider.GetItemsByTaxon(taxon.Id, prop.MetaField.IsSingleTaxon, prop.Name, itemType, filter, String.Empty, 0, 100, ref totalCount);
    return items;

Please add AnyContentItems to the Fluent API. It would really open up doors for custom modules I think. Thanks for all the help.

Posted by Community Admin on 12-Aug-2011 00:00

Hi Basem,

I have logged this in PITS.

Regards,
Radoslav Georgiev
the Telerik team

Do you want to have your say in the Sitefinity development roadmap? Do you want to know when a feature you requested is added or when a bug fixed? Explore the Telerik Public Issue Tracking system and vote to affect the priority of the items

This thread is closed