+1-888-365-2779
Try Now
More in this section

Forums / General Discussions / Search Index Documents & Images?

Search Index Documents & Images?

14 posts, 0 answered
  1. Greg
    Greg avatar
    82 posts
    Registered:
    08 Aug 2012
    08 Jul 2010
    Link to this post
    Can the search indexes be modified to search the documents and images libraries? We have a library with PDF's and just need them indexed based on title and/or description, not necessarily the full text within. Can someone let me know if this is possible?

    Thanks,

    Greg
  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    30 Sep 2016
    09 Jul 2010
    Link to this post
    Hi Greg Delorey,

    There is no built-in search index for Images and Documets module. You need to create a custom one. You could take a look at this blog post - In the mean time series (part 4): BONUS TRACK - "Products" module - implementing search index

    You need to create a custom provider and use 3rd party framework to extract the content of the files. We have API that will allow you to index the content, but we do not have API that allows you to extract the content from the PDF files. You could use some open source libraries as Apache PDFBox or iTextSharp.

    If you use PDFBox you can read the stream by using PDDocument.load(stream); and then call getText of  PDFTextStripper instance.

    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. Greg
    Greg avatar
    82 posts
    Registered:
    08 Aug 2012
    13 Jul 2010
    Link to this post
    Hey Ivan -

    Thanks for the reply. I'd imagine that this would be even easier if we were only interested in searching the file name and description, correct?

    Thanks,

    Greg
  4. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    30 Sep 2016
    13 Jul 2010
    Link to this post
    Hello Greg Delorey,

     In the mean time series (part 4): BONUS TRACK - "Products" module - implementing search index shows how to create a standard provider for GenericContent based modules like Images and Documents.
    Your provider could directly inherit from ContentIndexProvider and you have to override

    methods
    GetItemUrl - get the content item, its url and culture if you use localization
    Initialize - here the index settings are initialized

    properties

    Name - return name of the provider
    Description  - return some description
    ContentItemKeyImpl - return a search key
    ContentProviderKeyImpl - return a provider key
    GetDefaultContentProvider - get the default provider
    FilterExpression - return "Name='InVariantCulture';";

    skeleton

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Telerik.Cms.Engine;
    using Telerik.Libraries;
    using System.Globalization;
     
    /// <summary>
    /// Summary description for Libraries
    /// </summary>
    public class LibrariesIndexProvider : ContentIndexProvider
    {
            public LibrariesIndexProvider()
            {
            }
     
            public override string Name
            {
                get { return "LibrariesIndexProvider "; }
            }
     
            public override string Description
            {
                get { return "Provider_Descriptions"; }
            }
     
          
            protected override string ContentItemKeyImpl
            {
                get
                {
                    return "LibraryItem";
                }
            }
     
           
            protected override string ContentProviderKeyImpl
            {
                get
                {
                    return "LibraryProv";
                }
            }
     
     
            protected override string GetDefaultContentProvider()
            {
                return WLibraryManager.DefaultContentProvider;
            }
     
            public override string FilterExpression
            {
                get
                {
                    return "Name='InVariantCulture';";
                }
            }
     
     
     
     
            protected override string GetItemUrl(IContent contentItem, string singleItemUrl, CultureInfo culture)
            {
                if (String.IsNullOrEmpty(singleItemUrl))
                {
                  //
                }
                return base.GetItemUrl(contentItem, singleItemUrl, culture);
            }
     
     
            public override void Initialize(IDictionary<string, string> settings)
            {
     
                settings.TryGetValue("LibrariesIndexProvider", out this.provider);
     
                if (String.IsNullOrEmpty(this.itemPageUrl))
                    throw new ArgumentException(String.Format("CannotCreateAbsoluteUri", this.Name));
                base.Initialize(settings);
     
            }
     
            private string itemPageUrl = "~/downloadListIndexTest.aspx";
            public string provider = LibraryManager.DefaultContentProvider;
    }

    Index settings control

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using Telerik.Framework.Search;
    using System.Web.UI.WebControls;
     

    public class LibraryIndexSettings : CompositeControl, ISettingsControl
    {
        public LibraryIndexSettings()
        {
         
        }
     
        #region ISettingsControl Members
     
        public void InitSettings(IDictionary<string, string> indexSettings)
        {
        }
     
        public IDictionary<string, string> GetSettings()
        {
            return new Dictionary<string, string>();
        }
     
        #endregion
    }




    Best wishes,
    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. bemara57
    bemara57 avatar
    135 posts
    Registered:
    27 Mar 2008
    06 Oct 2010
    Link to this post
    I am getting an error trying to index the library, I think because it is trying to index the content field which is a byte[]. This is the error I am getting:
    -----------------------------------------

    Unable to cast object of type 'System.Byte[]' to type 'System.String'.

    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.InvalidCastException: Unable to cast object of type 'System.Byte[]' to type 'System.String'.

    Source Error:

    An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

    Stack Trace:

    [InvalidCastException: Unable to cast object of type 'System.Byte[]' to type 'System.String'.]
       Telerik.Cms.Engine.ContentIndexerInfo.GetData() +141
       Telerik.Search.Engine.Crawler.IndexContent(String provider, LinkedList`1 data, Boolean appendToIndex, Dictionary`2 indexers) +180
       Telerik.Search.Engine.Crawler.Index(String provider, String[] urls, LinkedList`1 data, Boolean appendToIndex) +150
       Telerik.Search.Engine.IndexingManager.StartIndexing(IIndexingService service, Boolean appendToIndex) +86
       Telerik.Search.Engine.IndexingService.Index(Boolean appendToIndex) +11
       Telerik.Search.WebControls.Admin.ControlPanel.Service_Command(Object sender, CommandEventArgs e) +334
       System.Web.UI.WebControls.LinkButton.OnCommand(CommandEventArgs e) +108
       System.Web.UI.WebControls.LinkButton.RaisePostBackEvent(String eventArgument) +135
       System.Web.UI.WebControls.LinkButton.System.Web.UI.IPostBackEventHandler.RaisePostBackEvent(String eventArgument) +10
       System.Web.UI.Page.RaisePostBackEvent(IPostBackEventHandler sourceControl, String eventArgument) +13
       System.Web.UI.Page.RaisePostBackEvent(NameValueCollection postData) +175
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1565
    
    -----------------------------

    Also this is the index provider I put together:
    public class LibrariesIndexProvider : ContentIndexProvider
     {
         public LibrariesIndexProvider()
         {
         }
     
         public override string Name
         {
             get { return "LibrariesIndexProvider"; }
         }
     
         public override string Description
         {
             get { return Messages.ProvidesIndexingDesc; }
         }
     
         protected override string ContentItemKeyImpl
         {
             get
             {
                 return "LibraryItem";
             }
         }
     
         protected override string ContentProviderKeyImpl
         {
             get
             {
                 return "LibraryProv";
             }
         }
     
         protected override string GetDefaultContentProvider()
         {
             return LibraryManager.DefaultContentProvider;
         }
     
         public override string FilterExpression
         {
             get
             {
                 return "Name='InVariantCulture';";
             }
         }
     
         /// <summary>
         /// Meta fields for this provider
         /// </summary>
         protected override string[] MetaFields
         {
             get
             {
                 return new string[]{
                     "Title"
                 };
             }
         }
     
         protected override string GetItemUrl(IContent contentItem, string singleItemUrl, CultureInfo culture)
         {
             if (String.IsNullOrEmpty(singleItemUrl))
             {
                 int idx = itemPageUrl.IndexOf('.');
                 if (idx != -1)
                     itemPageUrl = itemPageUrl.Substring(0, idx);
     
                 singleItemUrl = itemPageUrl;
             }
             return base.GetItemUrl(contentItem, singleItemUrl, culture);
         }
     
         public override void Initialize(IDictionary<string, string> settings)
         {
             itemPageUrl = settings["ItemPageUrl"];
             settings.TryGetValue("LibrariesIndexProvider", out this.provider);
     
             if (String.IsNullOrEmpty(itemPageUrl))
                 throw new ArgumentException(String.Format("CannotCreateAbsoluteUri", this.Name));
             base.Initialize(settings);
     
         }
     
         private string itemPageUrl;
         public string provider = LibraryManager.DefaultContentProvider;
     }

    public class LibrariesIndexSettingsControl : CompositeControl, ISettingsControl
    {
        #region Properties
     
        /// <summary>
        /// Gets or sets the Control Template path
        /// </summary>
        public string ControlTemplatePath
        {
            get
            {
                object o = ViewState["ControlTemplatePath"];
                if (o == null)
                    return "~/Sitefinity/Admin/ControlTemplates/Libraries/LibrariesIndexSettingsControl.ascx";
                return (string)o;
            }
            set
            {
                ViewState["ControlTemplatePath"] = value;
            }
        }
     
        /// <summary>
        /// Gets or sets the control template
        /// </summary>
        public ITemplate ControlTemplate
        {
            get
            {
                if (controlTemplate == null)
                    controlTemplate = ControlUtils.GetTemplate<DefaultTemplate>(ControlTemplatePath);
                return controlTemplate;
            }
            set
            {
                controlTemplate = value;
            }
        }
     
        /// <summary>
        /// Gets or Sets the name of the provider
        /// </summary>
        public string ProviderName
        {
            get
            {
                object o = ViewState["ProviderName"];
                if (o == null)
                    return String.Empty;
                return (string)o;
            }
            set
            {
                ViewState["ProviderName"] = value;
            }
        }
     
     
        /// <summary>
        /// Gets or Sets the page Url for displaying the news item
        /// </summary>
        public string SingleLibraryUrl
        {
            get
            {
                if (ctrlContainer.SingleLibraryUrl != null)
                    return ctrlContainer.SingleLibraryUrl.Text;
                return string.Empty;
            }
            set
            {
                ctrlContainer.SingleLibraryUrl.Text = value;
            }
        }
        #endregion
     
        #region Inherited Methods
     
        /// <summary>
        /// Overriden. Cancels the rendering of a beginning HTML tag for the control.
        /// </summary>
        /// <param name="writer">The HtmlTextWriter object used to render the markup.</param>
        public override void RenderBeginTag(HtmlTextWriter writer)
        {
        }
     
        /// <summary>
        /// Overriden. Cancels the rendering of an ending HTML tag for the control.
        /// </summary>
        /// <param name="writer">The HtmlTextWriter object used to render the markup.</param>
        public override void RenderEndTag(HtmlTextWriter writer)
        {
        }
     
        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation
        /// to create any child controls they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            ctrlContainer = new ControlContainer(this);
            ControlTemplate.InstantiateIn(ctrlContainer);
     
            properties = TypeDescriptor.GetProperties(this);
            PropertyDescriptor desc = properties.Find("SingleLibraryUrl", false);
     
            editorDialog = new PropertyEditorDialog();
            editorDialog.TypeContainer = this;
            editorDialog.PropertyChanged += editorDialog_PropertyChanged;
            Controls.Add(editorDialog);
     
            string[] provNames = null;
            int count = ConfigHelper.Handler.GenericContentProviders.Count;
            if (count > 1)
            {
                int i = 0;
                provNames = new string[count];
                foreach (Telerik.Libraries.Configuration.GenericContentElement element in ConfigHelper.Handler.GenericContentProviders)
                {
                    GlobalPermission perm = new GlobalPermission(
                        (GlobalPermissions)LibraryManager.SecurityRoots[element.ProviderName], CrudRights.View);
                    if (perm.CheckDemand())
                    {
                        provNames[i++] = element.ProviderName;
                    }
                }
            }
     
            ListControl list = ctrlContainer.ProviderName;
            if (provNames != null)
            {
                foreach (string name in provNames)
                {
                    if (!String.IsNullOrEmpty(name))
                    {
                        ListItem item = new ListItem(name.Replace('_', ' '), name);
                        list.Items.Add(item);
                    }
                }
            }
            ctrlContainer.ProviderNameLi.Visible = (list.Items.Count > 1);
     
            ctrlContainer.SelectLibraryUrl.CommandName = "Telerik.Cms.Web.UI.PageIndexUrlWebEditor, Telerik.Cms";
            ctrlContainer.SelectLibraryUrl.CommandArgument = desc.Name;
            ctrlContainer.SelectLibraryUrl.Command += SelectSingleLibraryUrl_Command;
            ctrlContainer.ProviderName.SelectedIndexChanged += ProviderName_SelectedIndexChanged;
     
            if (settings != null && settings.Count > 0)
            {
                ctrlContainer.ProviderName.SelectedValue = ProviderName = settings["LibrariesIndexProvider"];
                ctrlContainer.SingleLibraryUrl.Text = settings["ItemPageUrl"];
            }
     
            Controls.Add(ctrlContainer);
        }
     
        void ProviderName_SelectedIndexChanged(object sender, EventArgs e)
        {
            ProviderName = ((ListControl)sender).SelectedValue;
        }
     
        void SelectSingleLibraryUrl_Command(object sender, CommandEventArgs e)
        {
            object data;
            string name = (string)e.CommandArgument;
     
            PropertyDescriptor desc = properties.Find(name, false);
            data = desc.Converter.ConvertToInvariantString(this);
     
            editorDialog.Show(name, e.CommandName, data, this);
        }
     
        void editorDialog_PropertyChanged(object source, PropertyValueChangedEventArgs e)
        {
            string[] resultValue = ((string)e.PropertyValue).Split(';');
            SetProperty(this, properties, e.PropertyName, resultValue[1]);
        }
     
        private void SetProperty(object component, PropertyDescriptorCollection _properties, string name, object value)
        {
            PropertyDescriptor desc = _properties.Find(name, false);
            desc.SetValue(component, value);
        }
     
        /// <summary>
        /// It initializes the _settings.
        /// </summary>
        /// <param name="_settings">
        ///   The parameter contains the default values when a new provider is created (in IRssProviderModule implementation)
        ///   If the provider has already been created, the parameter contains the values saved in the database.
        /// </param>
        public void InitSettings(IDictionary<string, string> _settings)
        {
            settings = _settings;
        }
     
        /// <summary>
        /// Gets the newly edited settings.
        /// </summary>
        /// <returns> an object of type Dictionary that contains strings</returns>
        public IDictionary<string, string> GetSettings()
        {
            settings = new Dictionary<string, string>();
            settings["LibraryIndexProvider"] = ProviderName = ctrlContainer.ProviderName.SelectedValue;
            settings["ItemPageUrl"] = ctrlContainer.SingleLibraryUrl.Text;
            return settings;
        }
     
        #endregion
     
        #region Private Fields
     
        private PropertyDescriptorCollection properties;
        private ITemplate controlTemplate;
        private ControlContainer ctrlContainer;
        private IDictionary<string, string> settings;
        private PropertyEditorDialog editorDialog;
     
        #endregion
     
        #region DefaultTemplate
     
        /// <summary>
        /// The default template class
        /// </summary>
        protected class DefaultTemplate : ITemplate
        {
            /// <summary>
            /// Instantiates the specified control in the default template
            /// </summary>
            /// <param name="container">accepts a parameter of type Control</param>
            public void InstantiateIn(Control container)
            {
     
            }
        }
     
        #endregion
     
        #region Container
     
        /// <summary>
        /// The control container class
        /// </summary>
        protected class ControlContainer : GenericContainer<LibrariesIndexSettingsControl>
        {
            /// <summary>
            /// Constructs the control container
            /// </summary>
            /// <param name="owner">accepts a parameter of type RssSettingsControl</param>
            public ControlContainer(LibrariesIndexSettingsControl owner)
                : base(owner)
            {
            }
     
            /// <summary>
            /// Gets the control which displays the Provider Name.
            /// </summary>
            public ListControl ProviderName
            {
                get
                {
                    if (providerName == null)
                        providerName = FindRequiredControl<ListControl>("librariesProvider");
                    return providerName;
                }
            }
     
            /// <summary>
            /// Gets the control which displays the single library url which could be edited.
            /// </summary>
            public IEditableTextControl SingleLibraryUrl
            {
                get
                {
                    if (singleLibraryUrl == null)
                        singleLibraryUrl = (IEditableTextControl)FindControl(typeof(IEditableTextControl), "singleLibraryUrl", true);
                    return singleLibraryUrl;
                }
            }
     
     
            /// <summary>
            /// Gets the control which displays the post url in a link button which could be selected.
            /// </summary>
            public IButtonControl SelectLibraryUrl
            {
                get
                {
                    if (selectLibraryUrl == null)
                        selectLibraryUrl = (IButtonControl)FindControl(typeof(IButtonControl), "selectSingleLibraryUrl", true);
                    return selectLibraryUrl;
                }
            }
     
            /// <summary>
            /// Gets the control which displays the "li" tag with information about the Provider Name
            /// </summary>
            public HtmlGenericControl ProviderNameLi
            {
                get
                {
                    if (providerNameLi == null)
                        providerNameLi = FindRequiredControl<HtmlGenericControl>("providerNameLi");
                    return providerNameLi;
                }
            }
     
            private HtmlGenericControl providerNameLi;
            private IButtonControl selectLibraryUrl;
            private ListControl providerName;
            private IEditableTextControl singleLibraryUrl;
        }
     
        #endregion
    }

    public class LibrariesIndexViewControl : CompositeControl, ISearchViewControl
    {
        /// <summary>
        /// Gets or sets path of the external template that defines child controls of this control.
        /// </summary>
        public string TemplatePath
        {
            get
            {
                object o = this.ViewState["TemplatePath"];
                if (o == null)
                    return "~/Sitefinity/Admin/ControlTemplates/Libraries/LibrariesIndexViewSettingsControl.ascx";
                return (string)o;
            }
            set
            {
                this.ViewState["TemplatePath"] = value;
            }
        }
     
        /// <summary>
        /// Gets or sets the template of this control.
        /// </summary>
        public ITemplate ItemTemplate
        {
            get
            {
                if (this.itemTemplate == null)
                    this.itemTemplate = ControlUtils.GetTemplate<DefaultTemplate>(this.TemplatePath);
                return this.itemTemplate;
            }
        }
     
        /// <summary>
        /// Overriden. Called to populate the child control hierarchy. This is the main
        /// method to render the control's markup, since it is a CompositeControl and contains
        /// child controls.
        /// </summary>
        protected override void CreateChildControls()
        {
            this.container = new ControlContainer(this);
            this.ItemTemplate.InstantiateIn(this.container);
     
            this.container.ResultsPageUrl.Text = this.GetValue("ItemPageUrl", this.settings["ItemPageUrl"]);
     
            this.Controls.Add(this.container);
     
        }
     
        private string GetValue(string key, string value)
        {
            switch (key)
            {
                case "ItemPageUrl":
                    return String.IsNullOrEmpty(value) ? Messages.NotSet : value;
                default:
                    return "";
            }
        }
     
        /// <summary>
        /// Initializes settings for the control
        /// </summary>
        /// <param name="settings">a dictionary of strings</param>
        public void InitializeSettings(IDictionary<string, string> settings)
        {
            this.settings = settings;
        }
     
        #region Private Fields
     
        private ControlContainer container;
        private ITemplate itemTemplate;
        private IDictionary<string, string> settings;
     
        #endregion
     
        #region Default Template
     
        /// <summary>
        /// Implements the ITemplate interface
        /// </summary>
        protected class DefaultTemplate : ITemplate
        {
            /// <summary>
            /// Instantiates the specified control in the default template
            /// </summary>
            /// <param name="container">accepts a parameter of type Control</param>
            public void InstantiateIn(Control container)
            {
     
            }
        }
     
        #endregion
     
        #region Container
     
        /// <summary>
        /// The control container class
        /// </summary>
        protected class ControlContainer : GenericContainer<LibrariesIndexViewControl>
        {
            public ControlContainer(LibrariesIndexViewControl owner)
                : base(owner)
            {
            }
     
            public ITextControl ResultsPageUrl
            {
                get
                {
                    if (this.resultsPageUrl == null)
                        this.resultsPageUrl = (ITextControl)base.FindRequiredControl<Control>("resultsPageUrl");
                    return this.resultsPageUrl;
                }
            }
     
            private ITextControl resultsPageUrl;
        }
     
        #endregion
    }

  6. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    30 Sep 2016
    06 Oct 2010
    Link to this post
    Hi bemara57,

    You cannot create provider for libraries that inherits from ContentIndexProvider. You have to inherit from IIndexingServiceClient and implement IIndexerInfo class

    ContentIndexerInfo parse the content of IContent object and its Content property as string, since the Content property  of an IContent of Images and Documents module is Byte array.

    The GetData method of IIndexerInfo returns  byte array.

    sample

    public byte[] GetData()
       {
           string text = this._content;
           
           if (this.metaFields.Length > 0)
           {
               text += this.GetMetaData();
           }
           return this.Encoding.GetBytes(text);
       }

    In ContentIndexerInfo we case the Content property to string and this is from where the error comes from.

    All the best,
    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. bemara57
    bemara57 avatar
    135 posts
    Registered:
    27 Mar 2008
    07 Oct 2010
    Link to this post
    Thanks! Below is a working copy of what I ended up with. I externalized the searched meta fields to the app settings. Also you are able to specify a library to search from. A couple things I plan to do is make the library selector work and making it use embedded control templates. I hope this helps someone.

    public class LibrariesIndexProvider : IIndexingServiceClient
    {
        public event EventHandler<IndexEventArgs> Index;
     
        public string Name
        {
            get { return "LibrariesIndexProvider"; }
        }
     
        public string Description
        {
            get { return Messages.ProvidesIndexingDesc; }
        }
     
        /// <summary>
        /// Meta fields for this provider
        /// </summary>
        protected string[] MetaFields
        {
            get
            {
                if (!String.IsNullOrEmpty(ConfigurationManager.AppSettings[Constants.LIBRARIES_SEARCH_META_FIELDS]))
                {
                    return ConfigurationManager.AppSettings[Constants.LIBRARIES_SEARCH_META_FIELDS].Split(',');
                }
                else
                {
                    return new string[] {
                        "Name"
                    };
                }
            }
        }
     
        public IIndexerInfo[] GetContentToIndex()
        {
            LibraryManager manager = new LibraryManager(provider);
            List<IIndexerInfo> list = new List<IIndexerInfo>();
            IList contents = null;
             
            //GET FILES FROM SPECIFIED LIBRARY OR ALL LIBRARIES
            if (!String.IsNullOrEmpty(libraryId))
            {
                contents = manager.GetLibrary(new Guid(libraryId)).GetItems();
            }
            else
            {
                contents = manager.GetContent();
            }
     
            foreach (IContent item in contents)
            {
                Hashtable metaFields = new Hashtable();           
                foreach (string key in this.MetaFields)
                {
                    string value = (string)item.GetMetaData(key);
                    if (value != null)
                    {
                        metaFields.Add(key, value);
                    }
                }
     
                list.Add(new LibrariesIndexerInfo(
                    item.ID,
                    VirtualPathUtility.ToAbsolute(item.UrlWithExtension),
                    metaFields));
            }
     
            return list.ToArray();
        }
     
        public string[] GetUrlsToIndex()
        {
            return new string[0];
        }
     
        public void Initialize(IDictionary<string, string> settings)
        {
            libraryId = settings["LibraryId"];
            settings.TryGetValue("LibrariesIndexProvider", out this.provider);
        }
     
        private string libraryId;
        public string provider = LibraryManager.DefaultContentProvider;
    }

    public class LibrariesIndexerInfo : IIndexerInfo
     {
         #region Private variables
     
         private Hashtable _metaFields;
         private Guid _itemId;
         private string _url;
     
         #endregion
     
         #region IIndexerInfo Members
     
         public Encoding Encoding
         {
             get { return Encoding.UTF8; }
         }
     
         public byte[] GetData()
         {
             return this.Encoding.GetBytes(this.GetMetaData());
         }
     
         public string MimeType
         {
             get { return "text/html"; }
         }
     
         public string Path
         {
             get { return this._url; }
         }
     
         public Guid ItemID
         {
             get { return _itemId; }
         }
     
         public string Culture
         {
             get { return CultureInfo.CurrentCulture.Name; }
         }
     
         public string ResolveIndexPath()
         {
             return Path;
         }
     
         #endregion
     
         public LibrariesIndexerInfo(Guid itemId, string url, Hashtable metaFields)
         {
             this._itemId = itemId;
             this._url = url;
             this._metaFields = metaFields;
         }
     
         protected string GetMetaData()
         {
             StringBuilder sb = new StringBuilder();
             IDictionaryEnumerator meta = _metaFields.GetEnumerator();
     
             while (meta.MoveNext())
             {
                 sb.AppendLine();
                 sb.Append("<");
                 sb.Append(meta.Key);
                 sb.Append(">");
                 sb.Append(meta.Value.ToString());
                 sb.Append("</");
                 sb.Append(meta.Key);
                 sb.Append(">");
             }
             return sb.ToString();
         }
     }

    public class LibrariesIndexSettingsControl : CompositeControl, ISettingsControl
    {
        #region Properties
     
        /// <summary>
        /// Gets or sets the Control Template path
        /// </summary>
        public string ControlTemplatePath
        {
            get
            {
                object o = ViewState["ControlTemplatePath"];
                if (o == null)
                    return "~/Sitefinity/Admin/ControlTemplates/Libraries/LibrariesIndexSettingsControl.ascx";
                return (string)o;
            }
            set
            {
                ViewState["ControlTemplatePath"] = value;
            }
        }
     
        /// <summary>
        /// Gets or sets the control template
        /// </summary>
        public ITemplate ControlTemplate
        {
            get
            {
                if (controlTemplate == null)
                    controlTemplate = ControlUtils.GetTemplate<DefaultTemplate>(ControlTemplatePath);
                return controlTemplate;
            }
            set
            {
                controlTemplate = value;
            }
        }
     
        /// <summary>
        /// Gets or Sets the name of the provider
        /// </summary>
        public string ProviderName
        {
            get
            {
                object o = ViewState["ProviderName"];
                if (o == null)
                    return String.Empty;
                return (string)o;
            }
            set
            {
                ViewState["ProviderName"] = value;
            }
        }
     
     
        /// <summary>
        /// Gets or Sets the library id for retrieving the files
        /// </summary>
        public string LibraryId
        {
            get
            {
                if (ctrlContainer.LibraryId != null)
                    return ctrlContainer.LibraryId.Text;
                return string.Empty;
            }
            set
            {
                ctrlContainer.LibraryId.Text = value;
            }
        }
        #endregion
     
        #region Inherited Methods
     
        /// <summary>
        /// Overriden. Cancels the rendering of a beginning HTML tag for the control.
        /// </summary>
        /// <param name="writer">The HtmlTextWriter object used to render the markup.</param>
        public override void RenderBeginTag(HtmlTextWriter writer)
        {
        }
     
        /// <summary>
        /// Overriden. Cancels the rendering of an ending HTML tag for the control.
        /// </summary>
        /// <param name="writer">The HtmlTextWriter object used to render the markup.</param>
        public override void RenderEndTag(HtmlTextWriter writer)
        {
        }
     
        /// <summary>
        /// Called by the ASP.NET page framework to notify server controls that use composition-based implementation
        /// to create any child controls they contain in preparation for posting back or rendering.
        /// </summary>
        protected override void CreateChildControls()
        {
            ctrlContainer = new ControlContainer(this);
            ControlTemplate.InstantiateIn(ctrlContainer);
     
            properties = TypeDescriptor.GetProperties(this);
            PropertyDescriptor desc = properties.Find("LibraryId", false);
     
            editorDialog = new PropertyEditorDialog();
            editorDialog.TypeContainer = this;
            editorDialog.PropertyChanged += editorDialog_PropertyChanged;
            Controls.Add(editorDialog);
     
            string[] provNames = null;
            int count = ConfigHelper.Handler.GenericContentProviders.Count;
            if (count > 1)
            {
                int i = 0;
                provNames = new string[count];
                foreach (Telerik.Libraries.Configuration.GenericContentElement element in ConfigHelper.Handler.GenericContentProviders)
                {
                    GlobalPermission perm = new GlobalPermission(
                        (GlobalPermissions)LibraryManager.SecurityRoots[element.ProviderName], CrudRights.View);
                    if (perm.CheckDemand())
                    {
                        provNames[i++] = element.ProviderName;
                    }
                }
            }
     
            ListControl list = ctrlContainer.ProviderName;
            if (provNames != null)
            {
                foreach (string name in provNames)
                {
                    if (!String.IsNullOrEmpty(name))
                    {
                        ListItem item = new ListItem(name.Replace('_', ' '), name);
                        list.Items.Add(item);
                    }
                }
            }
            ctrlContainer.ProviderNameLi.Visible = (list.Items.Count > 1);
     
            ctrlContainer.SelectLibraryId.CommandName = "Telerik.Libraries.WebControls.LibrarySelector, Telerik.Libraries";
            ctrlContainer.SelectLibraryId.CommandArgument = desc.Name;
            ctrlContainer.SelectLibraryId.Command += SelectLibraryId_Command;
            ctrlContainer.ProviderName.SelectedIndexChanged += ProviderName_SelectedIndexChanged;
     
            if (settings != null && settings.Count > 0)
            {
                ctrlContainer.ProviderName.SelectedValue = ProviderName = settings["LibrariesIndexProvider"];
                ctrlContainer.LibraryId.Text = settings["LibraryId"];
            }
     
            Controls.Add(ctrlContainer);
        }
     
        void ProviderName_SelectedIndexChanged(object sender, EventArgs e)
        {
            ProviderName = ((ListControl)sender).SelectedValue;
        }
     
        void SelectLibraryId_Command(object sender, CommandEventArgs e)
        {
            object data;
            string name = (string)e.CommandArgument;
     
            PropertyDescriptor desc = properties.Find(name, false);
            data = desc.Converter.ConvertToInvariantString(this);
     
            editorDialog.Show(name, e.CommandName, data, this);
        }
     
        void editorDialog_PropertyChanged(object source, PropertyValueChangedEventArgs e)
        {
            string[] resultValue = ((string)e.PropertyValue).Split(';');
            SetProperty(this, properties, e.PropertyName, resultValue[1]);
        }
     
        private void SetProperty(object component, PropertyDescriptorCollection _properties, string name, object value)
        {
            PropertyDescriptor desc = _properties.Find(name, false);
            desc.SetValue(component, value);
        }
     
        /// <summary>
        /// It initializes the _settings.
        /// </summary>
        /// <param name="_settings">
        ///   The parameter contains the default values when a new provider is created (in IRssProviderModule implementation)
        ///   If the provider has already been created, the parameter contains the values saved in the database.
        /// </param>
        public void InitSettings(IDictionary<string, string> _settings)
        {
            settings = _settings;
        }
     
        /// <summary>
        /// Gets the newly edited settings.
        /// </summary>
        /// <returns> an object of type Dictionary that contains strings</returns>
        public IDictionary<string, string> GetSettings()
        {
            settings = new Dictionary<string, string>();
            settings["LibrariesIndexProvider"] = ProviderName = ctrlContainer.ProviderName.SelectedValue;
            settings["LibraryId"] = ctrlContainer.LibraryId.Text;
            return settings;
        }
     
        #endregion
     
        #region Private Fields
     
        private PropertyDescriptorCollection properties;
        private ITemplate controlTemplate;
        private ControlContainer ctrlContainer;
        private IDictionary<string, string> settings;
        private PropertyEditorDialog editorDialog;
     
        #endregion
     
        #region DefaultTemplate
     
        /// <summary>
        /// The default template class
        /// </summary>
        protected class DefaultTemplate : ITemplate
        {
            /// <summary>
            /// Instantiates the specified control in the default template
            /// </summary>
            /// <param name="container">accepts a parameter of type Control</param>
            public void InstantiateIn(Control container)
            {
     
            }
        }
     
        #endregion
     
        #region Container
     
        /// <summary>
        /// The control container class
        /// </summary>
        protected class ControlContainer : GenericContainer<LibrariesIndexSettingsControl>
        {
            /// <summary>
            /// Constructs the control container
            /// </summary>
            /// <param name="owner">accepts a parameter of type RssSettingsControl</param>
            public ControlContainer(LibrariesIndexSettingsControl owner)
                : base(owner)
            {
            }
     
            /// <summary>
            /// Gets the control which displays the Provider Name.
            /// </summary>
            public ListControl ProviderName
            {
                get
                {
                    if (providerName == null)
                        providerName = FindRequiredControl<ListControl>("librariesProvider");
                    return providerName;
                }
            }
     
            /// <summary>
            /// Gets the control which displays the single library url which could be edited.
            /// </summary>
            public IEditableTextControl LibraryId
            {
                get
                {
                    if (libraryId == null)
                        libraryId = (IEditableTextControl)FindControl(typeof(IEditableTextControl), "libraryId", true);
                    return libraryId;
                }
            }
     
     
            /// <summary>
            /// Gets the control which displays the post url in a link button which could be selected.
            /// </summary>
            public IButtonControl SelectLibraryId
            {
                get
                {
                    if (selectLibraryUrl == null)
                        selectLibraryUrl = (IButtonControl)FindControl(typeof(IButtonControl), "selectLibraryId", true);
                    return selectLibraryUrl;
                }
            }
     
            /// <summary>
            /// Gets the control which displays the "li" tag with information about the Provider Name
            /// </summary>
            public HtmlGenericControl ProviderNameLi
            {
                get
                {
                    if (providerNameLi == null)
                        providerNameLi = FindRequiredControl<HtmlGenericControl>("providerNameLi");
                    return providerNameLi;
                }
            }
     
            private HtmlGenericControl providerNameLi;
            private IButtonControl selectLibraryUrl;
            private ListControl providerName;
            private IEditableTextControl libraryId;
        }
     
        #endregion
    }

    public class LibrariesIndexViewControl : CompositeControl, ISearchViewControl
    {
        /// <summary>
        /// Gets or sets path of the external template that defines child controls of this control.
        /// </summary>
        public string TemplatePath
        {
            get
            {
                object o = this.ViewState["TemplatePath"];
                if (o == null)
                    return "~/Sitefinity/Admin/ControlTemplates/Libraries/LibrariesIndexViewSettingsControl.ascx";
                return (string)o;
            }
            set
            {
                this.ViewState["TemplatePath"] = value;
            }
        }
     
        /// <summary>
        /// Gets or sets the template of this control.
        /// </summary>
        public ITemplate ItemTemplate
        {
            get
            {
                if (this.itemTemplate == null)
                    this.itemTemplate = ControlUtils.GetTemplate<DefaultTemplate>(this.TemplatePath);
                return this.itemTemplate;
            }
        }
     
        /// <summary>
        /// Overriden. Called to populate the child control hierarchy. This is the main
        /// method to render the control's markup, since it is a CompositeControl and contains
        /// child controls.
        /// </summary>
        protected override void CreateChildControls()
        {
            this.container = new ControlContainer(this);
            this.ItemTemplate.InstantiateIn(this.container);
     
            this.container.LibraryName.Text = this.GetValue("LibraryId", this.settings["LibraryId"]);
     
            this.Controls.Add(this.container);
     
        }
     
        private string GetValue(string key, string value)
        {
            switch (key)
            {
                case "LibraryId":
                    if (!String.IsNullOrEmpty(value))
                    {
                        LibraryManager manager = new LibraryManager();
                        return manager.GetLibrary(new Guid(value)).Name;
                    }
                    else
                    {
                        return Messages.all;
                    }
                default:
                    return "";
            }
        }
     
        /// <summary>
        /// Initializes settings for the control
        /// </summary>
        /// <param name="settings">a dictionary of strings</param>
        public void InitializeSettings(IDictionary<string, string> settings)
        {
            this.settings = settings;
        }
     
        #region Private Fields
     
        private ControlContainer container;
        private ITemplate itemTemplate;
        private IDictionary<string, string> settings;
     
        #endregion
     
        #region Default Template
     
        /// <summary>
        /// Implements the ITemplate interface
        /// </summary>
        protected class DefaultTemplate : ITemplate
        {
            /// <summary>
            /// Instantiates the specified control in the default template
            /// </summary>
            /// <param name="container">accepts a parameter of type Control</param>
            public void InstantiateIn(Control container)
            {
     
            }
        }
     
        #endregion
     
        #region Container
     
        /// <summary>
        /// The control container class
        /// </summary>
        protected class ControlContainer : GenericContainer<LibrariesIndexViewControl>
        {
            public ControlContainer(LibrariesIndexViewControl owner)
                : base(owner)
            {
            }
     
            public ITextControl LibraryName
            {
                get
                {
                    if (this.libraryName == null)
                        this.libraryName = (ITextControl)base.FindRequiredControl<Control>("libraryName");
                    return this.libraryName;
                }
            }
     
            private ITextControl libraryName;
        }
     
        #endregion
    }

    LibrariesIndexSettingsControl.ascx
    <%@Register TagPrefix="cc1" Namespace="Telerik.Cms.Web.UI" Assembly="Telerik.Cms.Web.UI" %>
    <%@Register TagPrefix="cc2" Namespace="Telerik.Cms.Web.UI" Assembly="Telerik.Cms" %>
     
    <fieldset>
        <ul>
            <li runat="server" id="providerNameLi">
                <asp:Label ID="Label1" runat="server" Text="<%$Resources:LibrariesProvider %>" AssociatedControlID="librariesProvider"></asp:Label>
                <asp:DropDownList runat="server" ID="librariesProvider"></asp:DropDownList>
            </li>
            <li class="selector">
                <asp:Label ID="Label8" runat="server" AssociatedControlID="libraryId">
                    <asp:Literal ID="Literal1" runat="server" Text="<%$Resources:LibraryId %>"></asp:Literal>
                     *<cc1:LabelToolTip HelpBoxCssClass="HelpBox" id="labelHelpBox3" runat="server" ToolTipTitle="<%$Resources:LibraryIdDescriptionTitle %>" ToolTipText="<%$Resources:LibraryIdDescriptionContent %>" AlternateText="<%$Resources:LibraryIdTooltip %>"></cc1:LabelToolTip>
                </asp:Label>
                <asp:TextBox runat="server" ID="libraryId"  ValidationGroup="AddSearchIndex"></asp:TextBox>
                <asp:LinkButton runat="server" ID="selectLibraryId" Text="<%$Resources:Select %>" CssClass="picker" Visible="false"></asp:LinkButton>
            </li>           
        </ul>
    </fieldset>

    LibrariesIndexViewSettingsControl.ascx
    <ul>
        <li runat="server" id="resultsPageUrlLi">
            <asp:Literal ID="lblLibraryName" runat="server" Text="<%$Resources:LibraryName %>"></asp:Literal>
            <strong><asp:Literal ID="libraryName" runat="server"></asp:Literal></strong>
        </li>
    </ul>

  8. Miles
    Miles avatar
    32 posts
    Registered:
    23 Nov 2011
    19 Jan 2012
    Link to this post
    What namespaces did you use at the top of your documents?
  9. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    30 Sep 2016
    20 Jan 2012
    Link to this post
    Hello,

    I don't see how the namespace could be related to the custom index provider.

    Greetings,
    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
  10. Miles
    Miles avatar
    32 posts
    Registered:
    23 Nov 2011
    20 Jan 2012
    Link to this post
    The namespaces are important because I'm trying to implement some of your classes and I'm unable to find the objects that you're referring to. If I knew specifically which Telerik namespaces you were using in each class, I'd be able to use the code you posted.

    I'm currently unable to find all of these objects/interfaces:

    CompositeControl
    GenericContainer
    GenericContainer
    IIndexerInfo
    IIndexingServiceClient
    IndexEventArgs
    ISearchViewControl
    ISettingsControl
    PropertyDescriptorCollection
    PropertyEditorDialog
    PropertyValueChangedEventArgs

  11. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    30 Sep 2016
    21 Jan 2012
    Link to this post
    Hello,

    I will start with the first one, which is standard class from ASP.NET Framework

    http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.compositecontrol.aspx

    For Sitefinity specific namespaces you can use our developer manual

    http://www.sitefinity.com/help/developer-manual/introduction.html

    and API reference.

    Greetings,
    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
  12. Luke
    Luke avatar
    56 posts
    Registered:
    18 Mar 2013
    30 Sep 2015 in reply to Ivan Dimitrov
    Link to this post

    It is 2015, a few years later. In the time since this thread was created, humanity has seen great advances in 3D printing, genome engineering and we have even discovered water on Mars.

    Is it possible that by now that Sitefinity supports a functionality in which website front end users are able to search through a library of PDFs. Bear in mind this functionality exists on the back end. Admins can search and browse through document libraries and search keywords to filter, but the last time I checked Sitefinity did not support this basic modicum of user friendliness.

     I am getting a little tired of explaining to internal stakeholders why we cannot easily support even the most basic website usability features without commissioning custom development. 

  13. David
    David avatar
    99 posts
    Registered:
    06 Sep 2012
    25 May in reply to Luke
    Link to this post
    I'm in the same boat. Yesterday I told the IT director I could create a simple page that would contain a searchable document library for our BOARD MEMBERS. Now he has to explain that this is not possible with our choosen CMS.
  14. Svetoslav Manchev
    Svetoslav Manchev avatar
    735 posts
    Registered:
    30 Sep 2016
    31 May
    Link to this post
    Hi David,

    Sitefinity supports indexing of Media content. When create a search index you can select the media Items you want to index (screenshot).

    You can fine tune the results by permissions - per document or library and filter them based on that permissions:
    http://docs.sitefinity.com/search-widget-advanced-options#global-options-for-search-widgets

    Regards,
    Svetoslav Manchev
    Telerik
     
    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 Sitefinity CMS Ideas&Feedback Portal and vote to affect the priority of the items
     
Register for webinar
14 posts, 0 answered