Filtering ContentLocationInfo items in custom widget - Front- & Back-End Development - Front- & Back-End Development - Progress Community
 Front- & Back-End Development

Filtering ContentLocationInfo items in custom widget

  • Filtering ContentLocationInfo items in custom widget
  • Hi all,

    We developed a custom accordion widget, that can display multiple accordion items (using bootstrap accordion) using Sitefinity Feather.

    To manage the accordions and their items, we created a custom module, with a parent-child relationship (Accordion -> AccordionContent). In the backend view of the custom module, we now would like to show, on which pages the accordion/accordion content is used. For this, we  implemented IContentLocatableView in our AccordionController:

    public class AccordionController : Controller, IContentLocatableView
        public Guid AccordionId get; set;
         
        public ActionResult Index()
        
            //get accordion by AccordionId with DynamicModuleManager and return view...
        
         
        public bool? DisableCanonicalUrlMetaTag get; set;
         
        [NonAction]
        public IEnumerable<IContentLocationInfo> GetLocations()
        
            var locations = new List<ContentLocationInfo>();
            var manager = DynamicModuleManager.GetManager();
             
            var accordionType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.Teasers.Accordion");
            var accordion = manager.GetItem(accordionType, this.AccordionId) as DynamicContent; //THIS fails, as this.AccordionId is not set.
     
            var accordionLocationInfo = new ContentLocationInfo()
            
                ContentType = accordionType,
                ProviderName = manager.Provider.Name
            ;
     
            //create a filter expression that only includes the accordion with the correct Id
            var filterExpression = string.Format("(Id = 0 OR OriginalContentId = 0)", accordion.OriginalContentId.ToString("D"));
            accordionLocationInfo.Filters.Add(new BasicContentLocationFilter(filterExpression));
     
            locations.Add(accordionLocationInfo);
     
            //also add all child items of accordion (= AccordionContent)
            var accordionContentType = TypeResolutionService.ResolveType("Telerik.Sitefinity.DynamicTypes.Model.Teasers.AccordionContent");
            var accordionContentLocationInfo = new ContentLocationInfo()
            
                ContentType = accordionContentType,
                ProviderName = manager.Provider.Name
            ;
     
            //create a filter expression to filter the AccordionContent by parent Id
            var contentFilterExpression = string.Format("(Parent.Id = 0 OR Parent.OriginalContentId = 0)", accordion.OriginalContentId.ToString("D"));
            accordionContentLocationInfo.Filters.Add(new BasicContentLocationFilter(contentFilterExpression));
     
            locations.Add(accordionContentLocationInfo);
     
            return locations;
        

    And at this point we are stuck: When saving a page, Sitefinity correctly calls GetLocations() but the call occurs before the AccordionId property is set. Therefore, we cannot load our dynamic content by id and GetLocations throws an exception.

    Has anybody faced a similar problem and can give me a hint how to solve this?

    Thanks in advance,
    Matthias
  • Hello Matthias, Thank you for contacting Sitefinity support. In order the properties to be populated when the IContentLocatableView methods are executed, the properties should be part of the Model. Sample code Controller: using SitefinityWebApp.Mvc.Models; using System.Collections.Generic; using System.ComponentModel; using System.Web.Mvc; using Telerik.Sitefinity.ContentLocations; using Telerik.Sitefinity.Modules.News; using Telerik.Sitefinity.Mvc; using Telerik.Sitefinity.News.Model; namespace SitefinityWebApp.Mvc.Controllers [ControllerToolboxItem(Name = "NewsWidget", Title = "NewsWidget", SectionName = "MvcWidgets")] public class NewsWidgetController : Controller, IContentLocatableView [TypeConverter(typeof(ExpandableObjectConverter))] public NewsWidgetModel Model get if (this.model == null) this.model = new NewsWidgetModel(); return this.model; public bool? DisableCanonicalUrlMetaTag get; set; /// /// This is the default Action. /// public ActionResult Index() return View("Default"); public IEnumerable GetLocations() string itemTitle = this.Model.Title; if (string.IsNullOrEmpty(itemTitle)) return null; var locations = new List(); var providerName = NewsManager.GetManager().Provider.Name; var listItemsLocation = new ContentLocationInfo() ContentType = typeof(NewsItem), ProviderName = providerName ; string filter = string.Empty; filter = @"Title = """ + itemTitle + @""""; listItemsLocation.Filters.Add(new BasicContentLocationFilter(filter)); locations.Add(listItemsLocation); return locations; private NewsWidgetModel model; Model: using System; namespace SitefinityWebApp.Mvc.Models public class NewsWidgetModel public string Title get; set; For Ids use the OriginalContentId property. I have updated the forum thread as well. Regards, Nikola Zagorchev Telerik by Progress