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

Forums / Developing with Sitefinity / Multiple search result controls

Multiple search result controls

17 posts, 0 answered
  1. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    25 Jan 2010
    Link to this post
    Hello,

    I recently posted that I was creating a custom search index which I have now completed thanks to the help provided here. The search index searches for News, Events, PageIndex and also an external site which is added via a database with page content and title etc.

    Anyway what my employers would like is two search result controls or something similar on the same page, they would like one to display the main content of the site, so the News, Events and PageIndex, while the other will display a section along the lines of, "You may also be interested in this" which will provide search results from the external site.

    So initially I'm just wondering if this is possible? Or if theres another solution? Any code or links would be appreciated.

    Thanks

    Michael
  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    25 Jan 2010
    Link to this post
    Hello Michael Gamlin,

    Generally "You may also be interested in this" is used when there is some relation between the objects. You can easily add a new repeater to the SearchResults control and run the external page index together with the News, Events and PageIndex, but you need to relate the items by some criteria, like title or some common word in the snippet or the ResultItem

    Best wishes,
    Ivan Dimitrov
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  3. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    25 Jan 2010
    Link to this post
    I see where your coming from but this relates to a course search and ideally they would like to split the results from the main site and the course information.

    Would I be better implementing two radio buttons, in addition to the search box so the users can select between searching the main site and courses?
  4. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    25 Jan 2010
    Link to this post
    Hello Michael Gamlin,

    Then create two separate search indexes. The external one will be hidden and it should include only title of the page you want to refer. Once you load the first index, read the data from the query string and pass it to your external index. Create a simple repeater( or use the build-in SearchResults control - you do not need SearchBox control) the will show the external website SearchResultItem and create a label that says "You may find..." over the items the will be displayed. By doing so, you will run both the indexes only with one query.

    Greetings,
    Ivan Dimitrov
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  5. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    26 Jan 2010
    Link to this post
    Sorry about this but I'm new to Sitefinity and just wondering how I'd go about this?
  6. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    26 Jan 2010
    Link to this post
    Hello Michael Gamlin,

    You need to create a custom search results control that inherits from SearchResults. The main problem here is that you cannot have two indexes with the same name, so you have to pass the index value manually. Override CreateChildControls and set the external link explicitly.

    protected override void CreateChildControls()
    {
        base.CreateChildControls();
     
     
        this.layoutCnt.ResultsList.ItemDataBound += new RepeaterItemEventHandler(ResultsList_ItemDataBound);
        this.layoutCnt.ResultsList.DataBind();
     
        this.Controls.Clear();
     
        this.layoutCnt = new Container(this);
        this.LayoutTemplate.InstantiateIn(layoutCnt);
     
        if (!string.IsNullOrEmpty(Query))
        {
            string vPath = PathUtil.GetIndexPhysicalPath(this.IndexCatalogue);
            string nPath = PathUtil.GetIndexPhysicalPath(CustomCatalogName);
            if (Directory.Exists(vPath) && Directory.Exists(nPath))
            {
                // check if query string is supplied to select the current page
                if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[PageKey]))
                {
                    this.CurrentPage = Convert.ToInt32(
                        HttpContext.Current.Request.QueryString[PageKey]);
                }
     
                string searchQuery = Query;
                string message = string.Empty;
     
                bool isValid = this.EscapeSpecialChars ? this.EscapeSpecialChars : ValidateQuery(ref searchQuery, out message);
     
                if (isValid)
                {
                    int totalItems;
                    int totalItems2;
                    int startIndex = (this.CurrentPage - 1) * this.PostsPerPage;
     
                    try
                    {
                         
                        IList<ResultItem> CustomDataSource = SearchManager.Search(
                               searchQuery,
                               NewCatalogName,
                               startIndex,
                               this.PostsPerPage,
                               this.WordsMode,
                               this.EscapeSpecialChars,
                               out totalItems2);
     
     
                        foreach (ResultItem customItem in CustomDataSource )
                        {
                            newList.Add(customItem);
                        }
     
     
                        totalItems = totalItems + totalItems2;
     
                        int numberOfPages = (this.PostsPerPage == 0) ? 1 : (int)Math.Ceiling((double)totalItems / (double)this.PostsPerPage);
     
                        if (numberOfPages == 0 && totalItems > 0)
                            numberOfPages = 1;
     
                        string qeryTest = this.Query.Trim('\"');
                        ((Control)this.layoutCnt.ResultsStats).EnableViewState = false;
                        this.layoutCnt.ResultsStats.Text = string.Format(this.layoutCnt.ResultsStats.Text, totalItems, qeryTest);
     
                        if (this.AllowPaging)
                        {
                            this.layoutCnt.Pager1.SelectedPageChanged += new EventHandler<EventArgs>(Pager_SelectedPageChanged);
                            this.layoutCnt.Pager1.PageCount = numberOfPages;
                            this.layoutCnt.Pager1.SelectedPage = this.CurrentPage;
                        }
                        this.layoutCnt.ResultsList.DataSource = CustomDataSource;
     
                    }
                    catch (Telerik.Lucene.Net.QueryParsers.ParseException ex)
                    {
                        this.layoutCnt.ResultsStats.Text = "strange chars";
                        Log.Exception(ex);
                    }
                }
                else
                {
                    this.layoutCnt.ResultsStats.Text = message;
                }
            }
            else
            {
                this.layoutCnt.ResultsStats.Text = String.Format("InvalidIndex", this.IndexCatalogue);
            }
        }
        else
        {
            this.layoutCnt.ResultsStats.Text = String.Empty;
        }
     
        this.layoutCnt.ResultsList.ItemDataBound += new RepeaterItemEventHandler(ResultsList_ItemDataBound);
        this.layoutCnt.ResultsList.SkinID = this.SkinID;
     
        Controls.Add(this.layoutCnt);
        this.layoutCnt.ResultsList.DataBind();
     
    }

    You can implement a custom property where you set the index

    public string  CustomCatalogName
          {
              get
              {
                  return this.Cat;
              }
              set
              {
                  this.Cat = value;
              }
          }
     
          private string Cat;


    Best wishes,
    Ivan Dimitrov
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  7. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    26 Jan 2010
    Link to this post
    Hi,

    Thanks for the code thats extremely helpful, this will be my first custom control I've created, so I'm checking out the webinar you have on them and I'll let you know how I get on.

    Thanks

    Michael
  8. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    26 Jan 2010
    Link to this post
    Hi Michael Gamlin,

    You have to create a class that inherits from SearchResults control. You may find the following post useful - Using Templates in Custom Sitefinity Controls

    Best wishes,
    Ivan Dimitrov
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  9. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    26 Jan 2010
    Link to this post
    Thanks I found that just after I posted so working on it now.
  10. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    27 Jan 2010
    Link to this post
    Hi sorry about this just have a few more questions.

    Can I just ask what namespace is required for the area below to work?

    newList.Add(customItem) 

    Following on from that , you also gave several event handlers within the code, in paticular I'm having problems implementing the one below, as I've not previously dealt with RepeaterItemEventHandler and am not entirely sure as to what values it would be dealing with.

     

    Pager_SelectedPageChanged

     


    Just one last bit, once I've completed the Custom Search Result control, do I then just link it to the SearchResult.ascx template? I just need basic functionality for now I can work on providing the interface I'd like later.
  11. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    29 Jan 2010
    Link to this post
    Hello,

    Just to add I've made most of the sample you provided ok, however I'm wondering on two areas if there necessary, which can be found below?

    this.layoutCnt.ResultsList.ItemDataBound += new RepeaterItemEventHandler(ResultsList_ItemDataBound);  
                this.layoutCnt.ResultsList.DataBind();  
     
    this.layoutCnt.ResultsList.ItemDataBound += new RepeaterItemEventHandler(ResultsList_ItemDataBound);  
                this.layoutCnt.ResultsList.SkinID = this.SkinID;  
     
                Controls.Add(this.layoutCnt);  
                this.layoutCnt.ResultsList.DataBind(); 

    Further to this I now am creating a toolbox, in preparation for the template I'll be creating, but am short on knowledge as to what it needs to do, I've currently used your sample provided in one of your other threads, but having little luck with it. You can see what I have below:

    namespace CustomSearchResults  
    {  
     
        [System.ComponentModel.ToolboxItem(typeof(SearchResultsCustomToolboxItem))]  
        public class SearchResultsCustom : SearchResult  
        {  
        }  
     
     
    public class SearchResultsCustomToolboxItem : Telerik.Web.ToolboxItem  
    {
        #region Construction  
        public SearchResultsCustomToolboxItem()  
            : base(typeof(CustomSearchResults.SearchResultsCustom))  
        {  
            base.DisplayName = "SearchResults";  
            base.Description = "SearchResults";  
     
        }
        #endregion  
     
    }  
  12. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    29 Jan 2010
    Link to this post
    Hi Michael Gamlin,

    ItemDataBound - you do not have to subscribe twice for the same event. You need to add the container and bind the results list as shown in the initial code.

    ToolboxItem

    this line is not correct

    : base(typeof(CustomSearchResults.SearchResultsCustom))

    it should be

    : base(typeof(SearchResultsCustom))


    Greetings,
    Ivan Dimitrov
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  13. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    25 Nov 2016
    29 Jan 2010
    Link to this post
    Hi Michael Gamlin,

    ItemDataBound event - There is no point to subscribe twice for the same event. You can follow the initial code - it adds the container and then call DataBind of the repeater.

    ToolboxItem

    this line is not correct

    : base(typeof(CustomSearchResults.SearchResultsCustom))

    the correct one should be

    : base(typeof(CustomSearchResults))


    Greetings,
    Ivan Dimitrov
    the Telerik team

    Instantly find answers to your questions on the new Telerik Support Portal.
    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
  14. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    29 Jan 2010
    Link to this post
    Thanks for the quick response but what I don't really understand, is what will be happening within the event when its called? So I have my function to deal with the event, but not sure what should be occuring within it.

    void ResultsList_ItemDataBound(object sender, EventArgs e)  
            {  
            }  
     
  15. mcpdinkansas
    mcpdinkansas avatar
    102 posts
    Registered:
    22 Mar 2007
    07 Apr 2010
    Link to this post
    Has this been resolved? If so, please see my forum thread:

    http://www.sitefinity.com/support/forums/sitefinity-3-x/developing-with-sitefinity/custom-search-results.aspx

    Thanks
  16. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    11 May 2010
    Link to this post
    Just incase anyone wants the code I eventually got for future reference:

    ///<Summary>
    ///The following provides a control which can search for indexes which are not specified within the searchbox
    ///<Summary>
      
    using System;
    using System.Collections.Generic;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using Telerik.Search.Engine;
    using Telerik.Search.Common;
    using System.IO;
    using Telerik.Utilities;
    using Telerik.Search.WebControls;
    using System.ComponentModel;
    using Telerik.Cms.Web.UI;
    using Telerik.Framework.Web;
    using System.Web.UI.HtmlControls;
    using System.Globalization;
      
    namespace CustomSearchResults
    {
        #region ToolBox
        //This provides the settings for the toolbox (does not currently work)
        public class Test : System.Drawing.Design.ToolboxItem
        {
            public Test()
                : base(typeof(CustomSearchResult))
            {
                base.DisplayName = "CustomSearchResult";
                base.Description = "MC Search Control";
            }
        }
      
        #endregion
      
      
        #region Search Result
        //The main control
        [ToolboxData("<{0}:SearchResults runat=\"server\"></{0}:SearchResults>")]
        [DefaultProperty("SearchResultsUrl")]
        [ToolboxItem(typeof(Test))]
        public class CustomSearchResult : SearchResult
        {
      
            private CustomContainer custCnt;
            private ITemplate CustomSearch;
      
            //Provides the element to get and set the Title within the control
            [Category("Title")]
            public string Title
            {
                get
                {
                    object obj = this.ViewState["Title"];
                    if (obj != null)
                        return (string)obj;
                    return "You may also be interested in:";
                }
                set
                {
                    this.ViewState["Title"] = value;
                }
            }
      
            //Provides the element that gets and sets the Index to search
            [Category("Index")]
            public string IndexName
            {
                get
                {
                    object obj = this.ViewState["IndexName"];
                    if (obj != null)
                        return (string)obj;
                    return "CustomSearchIndex";
                }
                set
                {
                    this.ViewState["IndexName"] = value;
                }
            }
      
            //Overrides the default LayoutTemplatePath element and allows the user to change it if necessary
            public string LayoutTemplatePath
            {
                get
                {
                    object obj = this.ViewState["LayoutTemplatePath"];
                    if (obj != null)
                        return (string)obj;
                    // otherwise return default path of the Template. This should     
                    // be the path of the new template we have created   
                    return "~/UserControls/Custom/CustomSearchResult.ascx";
                }
                set
                {
                    this.ViewState["LayoutTemplatePath"] = value;
                }
            }
      
            //Sets up and binds the control
            protected override void CreateChildControls()
            {
                string index;
                string title;
      
                //Clears the control and initializes the template to be used
                this.Controls.Clear();
                this.InitializeTemplate();
      
                //Adds the container to the control
                this.Controls.Add(this.custCnt);
                //Sets up the Databound event
                this.custCnt.ResultsList.ItemDataBound += new RepeaterItemEventHandler(ResultsList_ItemDataBound);
                this.custCnt.ResultsList.DataBind();
      
                //Checks to see if the query string is null or empty
                if (!string.IsNullOrEmpty(Query))
                {
                    //The IndexName provided from the control is passed to a temp string
                    index = IndexName;
                    //Retrieves the physical path of the index and checks the segments exist
                    string nPath = PathUtil.GetIndexPhysicalPath(index);
                    if (Directory.Exists(nPath))
                    {
                        if (!string.IsNullOrEmpty(HttpContext.Current.Request.QueryString[PageKey]))
                        {
                            this.CurrentPage = Convert.ToInt32(
                                HttpContext.Current.Request.QueryString[PageKey]);
                        }
      
                        string searchQuery = Query;
                        string message = string.Empty;
                        //Checks that the query is valid
                        bool isValid = this.EscapeSpecialChars ? this.EscapeSpecialChars : ValidateQuery(ref searchQuery, out message);
      
                        if (isValid)
                        {
                            int totalItems;
                            int startIndex = (this.CurrentPage - 1) * this.PostsPerPage;
      
                            try
                            {
                                //Retrieves the search information and total items collected
                                IList<ResultItem> CustomDataSource = SearchManager.Search(
                                       searchQuery,
                                       index,
                                       startIndex,
                                       this.PostsPerPage,
                                       this.WordsMode,
                                       this.EscapeSpecialChars,
                                       out totalItems);
      
                                //Works out the number of pages needed to display results
                                int numberOfPages = (this.PostsPerPage == 0) ? 1 : (int)Math.Ceiling((double)totalItems / (double)this.PostsPerPage);
      
                                if (numberOfPages == 0 && totalItems > 0)
                                    numberOfPages = 1;
                                //Gets the title set by the user that they would like to use
                                title = Title;
      
                                //Trims the original query to remove unwanted characters
                                string qeryTest = this.Query.Trim('\"');
                                ((Control)this.custCnt.ResultStats).EnableViewState = false;
                                //Passes the appropriate values to the .ascx file
                                this.custCnt.ResultStats.Text = string.Format(this.custCnt.ResultStats.Text, title, totalItems, qeryTest);
      
                                //If paging is allowed sets up page changed event handler, the PageCount and also the current page
                                if (this.AllowPaging)
                                {
                                    this.custCnt.Pager1.SelectedPageChanged += new EventHandler<EventArgs>(Pager_SelectedPageChanged);
                                    this.custCnt.Pager1.PageCount = numberOfPages;
                                    this.custCnt.Pager1.SelectedPage = this.CurrentPage;
                                }
                                //Binds the data to be displayed
                                this.custCnt.ResultsList.DataSource = CustomDataSource;
                                this.custCnt.ResultsList.DataBind();
      
                            }
                            catch (Telerik.Lucene.Net.QueryParsers.ParseException ex)
                            {
                                this.custCnt.ResultStats.Text = "strange chars";
                                Log.Exception(ex);
                            }
                        }
                        else
                        {
                            //Provides an error if the query is not valid
                            this.custCnt.ResultStats.Text = message;
                        }
                    }
                    else
                    {
                        //Provides an error if an Invalid index is provided
                        this.custCnt.ResultStats.Text = String.Format("InvalidIndex", this.IndexCatalogue);
                    }
                }
                else
                {
                    //Provides result if query is null or empty
                    this.custCnt.ResultStats.Text = String.Empty;
                }
            }
      
  17. Laura
    Laura avatar
    311 posts
    Registered:
    25 Feb 2008
    03 Jun 2010
    Link to this post
    Is there a 'dummed down' version of this?  I am getting errors with this example as well as the example on http://www.sitefinity.com/devnet/forums/sitefinity-3-x/developing-with-sitefinity/custom-search-results.aspx and they are quite different. 
    I just need something basic so that when I get the results, I can then display page results based on the user's role.

    Thank you!
Register for webinar
17 posts, 0 answered