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

Forums / Developing with Sitefinity / Creating Search Index for Custom Module

Creating Search Index for Custom Module

11 posts, 0 answered
  1. Travis
    Travis avatar
    86 posts
    Registered:
    15 Oct 2008
    04 Mar 2010
    Link to this post
    Hello,

    I have created two custom modules (i'm not sure of the exact terminology to tell you how these modules function, but, the are "pluggable" modules, with custom providers, controls and all that jazz) and I would like to create an index for this, to tie it into the site search. I did a bit of searching, and what I could find was related to extending existing indexes, or creating indexes based off content stored in the CMS (in the case of these modules, the content is stored in custom tables, as opposed to in the cms tables).

    So, is this possible? if so, how do I do this?

    Thanks
  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    04 Mar 2010
    Link to this post
    Hello Travis,

    I believe that this post will help you - BONUS TRACK - "Products" module - implementing search index.
    None of our index providers looks into the database. All providers work with interface object and API.

    Regards,
    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. Travis
    Travis avatar
    86 posts
    Registered:
    15 Oct 2008
    04 Mar 2010
    Link to this post
    Thanks Ivan, this seems to have worked to a point. I can add my "ProjectsIndex" to the new Search Index i am trying to create, however, when I press save, it throws an error:

    Server Error in '/Sitefinity' Application.

    No provider with name 'Sitefinity' has not been set

    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.Configuration.ConfigurationErrorsException: No provider with name 'Sitefinity' has not been set

    Source Error:

    Line 97: 			if (String.IsNullOrEmpty(projectsPageUrl))
    Line 98: throw new ArgumentException(String.Format("CannotCreateAbsoluteUri"));
    Line 99: base.Initialize(settings);
    Line 100: }
    Line 101: private string projectsProvider;

    Source File: C:\Inetpub\wwwroot\FlynnCMS\Projects\Providers\ProjectsIndexProvider.cs    Line: 99

    Stack Trace:

    [ConfigurationErrorsException: No provider with name 'Sitefinity' has not been set]
    Telerik.ManagerBase`1.SetProvider(String providerName) +296
    Telerik.ManagerBase`1..ctor(String providerName) +169
    Telerik.Cms.Engine.ContentManager..ctor(String providerName) +52
    Telerik.Cms.Engine.ContentIndexProvider.CreateManager(String providerName) +49
    Telerik.Cms.Engine.ContentIndexProvider.Initialize(IDictionary`2 settings) +140
    Projects.Providers.ProjectsIndexProvider.Initialize(IDictionary`2 settings) in C:\Inetpub\wwwroot\FlynnCMS\Projects\Providers\ProjectsIndexProvider.cs:99
    Telerik.Search.Engine.IndexingService..ctor(IIndexingServiceInfo settings) +457
    Telerik.Search.Engine.IndexingManager.Initialize() +1602
    Telerik.Search.WebControls.Admin.ControlPanel.EditServiceButton_Command(Object sender, CommandEventArgs e) +2372
    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) +6741
    System.Web.UI.Page.ProcessRequest(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +242
    System.Web.UI.Page.ProcessRequest() +80
    System.Web.UI.Page.ProcessRequestWithNoAssert(HttpContext context) +21
    System.Web.UI.Page.ProcessRequest(HttpContext context) +49
    ASP.sitefinity_admin_cmsadmin_services_aspx.ProcessRequest(HttpContext context) in c:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\Temporary ASP.NET Files\sitefinity\c9ddfea0\fc0b3bae\App_Web_dfnpqtz4.14.cs:0
    System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +181
    System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +75

    Any idea why this might be happening? I copied most of the code from that tutorial, though, I left out the security parts, because this module does not leverage the security model. I should also note that the Index does get saved, but trying to start indexing results in this same error.
  4. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    05 Mar 2010
    Link to this post
    Hi Travis,

    It seems that you have not set Generic Content based provider in your web condfig or you are using a non existing provide with this index. The provider is populated from ConfigHelper.Handler.GenericContentProviders. The settings dictionary is populated by ProductsIndexSettings control.

    Sincerely yours,
    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. Travis
    Travis avatar
    86 posts
    Registered:
    15 Oct 2008
    05 Mar 2010
    Link to this post
    Hi Ivan,

    In my web.config, I have the following code:

    <projects defaultProvider="Sitefinity">
              <providers>
                  <clear />
                  <add name="Sitefinity" type="Projects.Providers.DefaultProvider, Projects" />
              </providers>
          </projects>

    I tried adding the following within the <projects> tag (I apologize, I'm not experienced in modifying the providers too much)

    <genericContentProviders><br>              <add providerName="Projects" urlRewriteFormat="Projects/[Name].aspx" urlWhitespaceChar="_" urlDateTimeFormat="yyyy-MM-dd" /><br>          </genericContentProviders>

    I'm now getting the error "The given key was not present in the dictionary." Nothing is going into the dropdown on the ProjectsIndexSettings control, so when it attempts to pull a value from there, it gets nothing. I noticed in the web.config for the sample project that Products is a generic content module and has its meta fields defined in there. Would this have anything to do with it?
  6. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    05 Mar 2010
    Link to this post
    Hi Travis,

    The provider names should be the same in both sections. Also I ran the module, the download expose the full code which you just have to attach to an project. The content indexing service is implemented in this sample - Sample Generic Content based module: Products module as well so you can observe it.

    Kind regards,
    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. Travis
    Travis avatar
    86 posts
    Registered:
    15 Oct 2008
    05 Mar 2010
    Link to this post
    I have changed the provider names to be "Sitefinity" in both the <projects><providers> area and the <projects><genericContentProviders> area, and i'm still getting the same error.

    this area of my web.config looked like this

    <projects defaultProvider="Sitefinity">
              <genericContentProviders>
                  <add providerName="Sitefinity" urlRewriteFormat="Projects/[Name].aspx" urlWhitespaceChar="_" urlDateTimeFormat="yyyy-MM-dd" />
              </genericContentProviders>
              <providers>
                  <clear />
                  <add name="Sitefinity" type="Projects.Providers.DefaultProvider, Projects" />
              </providers>
          </projects>


    I am not using the meta fields in the web.config, like the example shows, and I'm not sure if that's an issue? is it?

    Trying to follow the instructions in the linked article, pasting the code (and modifying it to read "projects" instead of "products") from the last step results in an error, telling me that "projects" is an unrecognized element. My module shows up fine. My module works fine. It is only the indexing that is not working.

    My module inherits from the WebModule class, as opposed the SecuredModule class, and I implement the IIndexingSupportModule interface as was outlined in the original link you posted.
  8. Travis
    Travis avatar
    86 posts
    Registered:
    15 Oct 2008
    05 Mar 2010
    Link to this post
    The application crashes in the ProjectsIndexProvider.cs class. In the Initialize function, when attempting to do base.Initialize(settings);

    I believe this is because one of the two keys, the ProjectIndexProvider is null.

    "ProjectIndexProvider" which is null and "ProjectPageUrl", which is set to the value i selected when I set up my index.

    It seems to me that it is trying to pull the Provider name from the invisible drop down list that appears on the ProjectsIndexSettingsControl.ascx file. This drop down list is empty. Shouldn't it have a value in it?
  9. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    08 Mar 2010
    Link to this post
    Hello Travis,

    Try using this code

    protected override string GetDefaultContentProvider()
     {
         if (!string.IsNullOrEmpty(this.moduleProvider))
             return this.moduleProvider;
         return ModuleManager.DefaultContentProvider;
     }      
     
    public override void Initialize(IDictionary<string, string> settings)
     {
         this.newsPageUrl = settings["ModulePageUrl"];
         settings.TryGetValue("ModuleIndexProvider", out this.moduleProvider);
     
         if (String.IsNullOrEmpty(this.modulePageUrl))
             throw new ArgumentException(String.Format("CannotCreateAbsoluteUri", this.Name));
         base.Initialize(settings);
      
     }
     
     private string moduleProvider;
     private string modulePageUrl;

    In the base class we call GetDefaultContentProvider() method which gets the provider and pass it to ContentManager class.

    Also in your settings control you can populate the DropDownList in CreateChildControls method. You should have a public ViewState property to persist the selected provider

    public string ProviderName
    {
        get
        {
            object o = this.ViewState["ProviderName"];
            if (o == null)
                return String.Empty;
            return (string)o;
        }
        set
        {
            this.ViewState["ProviderName"] = value;
        }
    }


    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.
  10. Travis
    Travis avatar
    86 posts
    Registered:
    15 Oct 2008
    08 Mar 2010
    Link to this post
    Hi Ivan,

    I have similar code to this in the module already. In my ProjectsIndexProvider, I have the following code:

    protected override string GetDefaultContentProvider()
            {
                if (!string.IsNullOrEmpty(projectsProvider))
                return projectsProvider;
                return new ProjectsManager().DefaultProvider;
            }

    public override void Initialize(IDictionary<string, string> settings)
            {
                projectsPageUrl = settings["ProjectPageUrl"];
                settings.TryGetValue("ProjectsProvider", out projectsProvider);
                if (String.IsNullOrEmpty(projectsPageUrl))
                    throw new ArgumentException(String.Format("CannotCreateAbsoluteUri"));
                base.Initialize(settings);
            }

    I have tried to re-implement the indexing from the tutorial, but I am still getting the same error. When you say "Also in your settings control you can populate the DropDownList in CreateChildControls method. You should have a public ViewState property to persist the selected provider" are you suggesting that I should be manually populating that drop down? I know I mentioned that the drop down is empty, but, if that's normal then, that's fine. I just want to get this working, and I'm contiunally getting the "No provider with name 'Sitefinity' has not been set" error when attempting to save my index. What should my provider name be? Should it be "Sitefinity" as is specified in my web.config on the following lines:

    <projects defaultProvider="Sitefinity">
              <genericContentProviders>
                  <add providerName="Sitefinity" urlRewriteFormat="[Name].aspx" urlWhitespaceChar="_" />
              </genericContentProviders>
              <providers>
                  <clear />
                  <add name="Sitefinity" type="Projects.Providers.DefaultProvider, Projects" />
              </providers>
          </projects>

    or should it be something else?

    Also, of note, in my IndexSettingsControl, at the end of the CreateChildControls method, the number of items in the settings array is 0. Shouldn't it be 1?
  11. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    12 Sep 2017
    11 Mar 2010
    Link to this post
    Hi Travis,

    You are trying to get ProjectProvider, since you have specified ProjectIndexProvider in the settings control. The Initialize method uses Dictionary of settings passed from your settings control

    SettingsControl

    protected override void CreateChildControls()
           {
               this.properties = TypeDescriptor.GetProperties(this);
               PropertyDescriptor desc = this.properties.Find("ItemUrl", false);
     
               this.editorDialog = new PropertyEditorDialog();
               this.editorDialog.TypeContainer = this;
               this.editorDialog.PropertyChanged += this.editorDialog_PropertyChanged;
               this.Controls.Add(this.editorDialog);
     
               ......
                                   .....
                   this.ProviderNameList.SelectedValue = this.ProviderName = settings["ModuleIndexProvider"];
                   this.SingleItemUrlText.Text = settings["ItemsPageUrl"];
               }
     
               this.Controls.Add(this.Container);
           }
     
           void ProviderName_SelectedIndexChanged(object sender, EventArgs e)
           {
               this.ProviderName = ((ListControl)sender).SelectedValue;
           }
     
           void SelectSingleItemUrl_Command(object sender, CommandEventArgs e)
           {
               string name = (string)e.CommandArgument;
     
               PropertyDescriptor desc = this.properties.Find(name, false);
               object data = desc.Converter.ConvertToInvariantString(this);
     
               this.editorDialog.Show(name, e.CommandName, data, this);
           }
     
           void editorDialog_PropertyChanged(object source, PropertyValueChangedEventArgs e)
           {
               string[] resultValue = ((string)e.PropertyValue).Split(';');
               this.SetProperty(this, this.properties, e.PropertyName, resultValue[1]);
           }
     
           private void SetProperty(object component, PropertyDescriptorCollection props, string name, object value)
           {
               PropertyDescriptor desc = props.Find(name, false);
               desc.SetValue(component, value);
           }
     
           public void InitSettings(IDictionary<string, string> indexSettings)
           {
               this.settings = indexSettings;
           }
     
         
           public IDictionary<string, string> GetSettings()
           {
               this.settings = new Dictionary<string, string>();
               this.settings["ModuleIndexProvider"] = this.ProviderName = this.ProviderNameList.SelectedValue;
               this.settings["ItemsPageUrl"] = this.SingleItemUrlText.Text;
               return this.settings;
           }

    ModuleIndexProvider

    public override void Initialize(IDictionary<string, string> settings)
            {
                this.itemPageUrl= settings["ItemsPageUrl"];
                settings.TryGetValue("ModuleIndexProvider", out this.moduleProvider);
     
                if (String.IsNullOrEmpty(this.itemPageUrl))
                    throw new ArgumentException(String.Format("CannotCreateAbsoluteUri", this.Name));
                base.Initialize(settings);
             
            }
     
            private string moduleProvider;
            private string itemPageUrl;

    If your module directly implements IIndexingSupportModule you should have the lines below.

    IServiceClientInfo[] IIndexingSupportModule.GetSeviceClients()
        {
            return new IServiceClientInfo[]
                {
                    new IndexingServiceClientInfo("ModuleIndex"
                        , typeof(ModuleIndexProvider)
                        , typeof(ModuleIndexSettingsControl).FullName
                        , typeof(ModuleIndexViewControl).FullName
                        , "ModuleIndexProvider"
                        )
                };
        }

    Your web.config settings are not the regular one

    this is the correct setting that you should have if your module is Generic Content based

    <projects defaultProvider="Sitefinity">
       <genericContentProviders>
         <add providerName="Sitefinity" urlRewriteFormat="[Name].aspx" urlWhitespaceChar="_" />
       </genericContentProviders>
    </projects>

    The setting below illustrates provider's registration of not GenericContent based module.

    <projects defaultProvider="Sitefinity">
       <providers>
         <clear />
            <add name="Sitefinity" type="Projects.Providers.DefaultProvider, Projects" />
       </providers>
     </projects>

    In your case your you have mixed the configuration.

    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.
Register for webinar
11 posts, 0 answered