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

Forums / Developing with Sitefinity / Over riding standard template

Over riding standard template

23 posts, 1 answered
  1. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    10 Feb 2010
    Link to this post
    Hello,

    I'm currently developing a custom search result custom control to search a custom index I've created while a 2nd standard search result will display results from aother standard index.

    My custom search result inherits from Telerik.Search.Webcontrols.SearchResult, however I want to override the default template and use my own.

    After I upload my Custom Control and add my custom search result to a webpage it uses the standard template, but when I change it to use my template in the appearances section a range of errors are displayed within the template control, relating to sections that I don't really need or want to implement, such as: A required control was not found in the template for "~/UserControls/Custom/CustomSearchResult.ascx". The required control must be assingable form type "System.Web.UI.Control" and must have ID "rptResults".

    What I want to do is be able to override the standard embeded template, so I'm trying to find out if this is possible.

    If you require further clarification, please let me know.
  2. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    10 Feb 2010
    Link to this post
    Hello Michael Gamlin,

    There are required controls that you cannot remove easily. In your template you should have repeater control with ID="rptResults", pager control with ID="pager1" and ITextControl control with ID="ResultsStats" There is a property that sets the template, but you cannot access it from your custom class, so the better option here is modifying the exsisting one. If you do not call  the base of  CreateChildControls() the container that looks for controls and SearchResults template will not be instantiated, but you need to implement your own item template that inherits from ITemplate, custom container Container : GenericContainer<SearchResultCustom> and then instantiate them in your custom class - CreateChildControls().

    All the best,
    Ivan Dimitrov
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
  3. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    11 Feb 2010
    Link to this post
    Hello Ivan,

    Thank you for the reply, I've created my own iTemplate and am initializing that, I've also created my own custom container inherting from GenericContainer. The issue I can see is that CreateChildControls I currently have uses layoutCnt which has certain attributes it looks like I need such as layoutCnt.ResultsList and layoutCnt.ResultsStats.

    To show you what I mean, I've included some of my code below (note that not all areas are fully implemented yet):

    public class CustomSearchResult : SearchResult
        {
      
            private CustomContainer custCnt;   
            private ITemplate CustomSearch;  
      
      
            public string Title
            {
                get;
                set;
            }
      
            public string CustomCatalogName
            {
                //set the index name or location to search, in this instance CustomIndex
                get;
                set;
            }
      
            public string CustomSearchTemplatePath   
            {   
                get  
                {   
                    object obj = this.ViewState["CustomSearchTemplatePath"];   
                    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["CustomSearchTemplatePath"] = value;   
                }   
            }
      
            private class CustomContainer : GenericContainer<CustomList>
            {
                private Literal title;
      
                public Literal Title
                {
                    get
                    {
                        if (this.title == null)
                        {
                            this.title = base.FindRequiredControl<Literal>("Title");
                        }
                        return this.title;
                    }
                }
      
                public CustomContainer(CustomSearchResult owner) : base(owner)
                {
                }  
            }
      
            protected override void CreateChildControls()
            {
                this.Controls.Clear();
                base.CreateChildControls();
                this.InitializeTemplate();

    Template:

     

    protected virtual void InitializeTemplate()
            {
                this.custCnt = new CustomContainer(this);
                this.CustomSearch = ControlUtils.GetTemplate<DefaultCustomTemplate>(this.CustomSearchTemplatePath);
                this.CustomSearch.InstantiateIn(this.custCnt);
            }
      
            protected class DefaultCustomTemplate : ITemplate
            {
                /// <summary>   
                /// When implemented by a class, defines the object that child controls and templates belong to. These child controls are in turn defined within an inline template.   
                /// </summary>   
                /// <param name="container">The object to contain the instances of controls from the inline template.</param>   
                public void InstantiateIn(Control container)
                {
                    throw new NotImplementedException("Default control designer not implemented!");
                }
            }

     

     

     

    The areas of layoutCnt that I'm concerned about:

    this.layoutCnt.ResultsList.ItemDataBound += new RepeaterItemEventHandler(ResultsList_ItemDataBound);
                this.layoutCnt.ResultsList.DataBind();
      
    ((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); //Find out where this is called from
                                    this.layoutCnt.Pager1.PageCount = numberOfPages;
                                    this.layoutCnt.Pager1.SelectedPage = this.CurrentPage;
                                }

  4. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    11 Feb 2010
    Link to this post
    Hello Michael Gamlin,

    In CreateChildControls you are using your custom container for which you have only defined a Literal control, since you are trying to call a control of type Repeater - ResultsList.

    Sincerely yours,
    Ivan Dimitrov
    the Telerik team

    Watch a video on how to optimize your support resource searches and check out more tips on the blogs.
    Follow the status of features or bugs in PITS and vote for them to affect their priority.
  5. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    11 Feb 2010
    Link to this post
    Hello Ivan,

    Are there any definitions I can review for the functionality they provide as I'm not sure what information I need to include or retrieve within the repeater - ResultsList or String - ResultsStats.

    *Update* I'm currently getting my collegue to provide me with the required classes

    Thanks for the excellent support.

    Michael
  6. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    11 Feb 2010
    Link to this post
    Hi Michael Gamlin,

    ResultsList is a repeater that has ID="rptResults" in SearchResults template. It displays all result items return by the query
    ResultsStats is ITextControl that has ID="ResultsStats". It shows the number of items that have been found - "Found 16 pages for...."

    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.
  7. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    11 Feb 2010
    Link to this post
    Thanks,

    Just one final question, I need to override IndexCatalogue as I need to specifiy one paticular index that I want to search, which will not be included in the Search Box. So how would this be undertaken?

    Michael
  8. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    11 Feb 2010
    Link to this post
    Hi Michael Gamlin,

    You should crate a property where you enter the name of the another index. Then merge both indexes in one in IList<ResultItem> and display this list on the public side.

    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.
  9. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    11 Feb 2010
    Link to this post
    See what I would ideally like to do is have a normal SearchResult which will be linked to a standard index through a SearchBox, including news items and blog posts.

    While I have a second CustomSearchResult (the one I'm creating), placed on a different part of the page, which will perform the same query but only on a custom index that I've created, rather than having them in within the same SearchResult box.

    Is this possible if I set the index to search explicitly?

    So for example as you can see below I set the Index, then provide that as the index that should be searched.

    if (!string.IsNullOrEmpty(Query))
                {
                    string nPath = "CustomIndex";
                    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;
      
                        bool isValid = this.EscapeSpecialChars ? this.EscapeSpecialChars : ValidateQuery(ref searchQuery, out message);
      
                        if (isValid)
                        {
                            int totalItems;
                            int startIndex = (this.CurrentPage - 1) * this.PostsPerPage;
      
                            try
                            {
                                IList<ResultItem> CustomDataSource = SearchManager.Search(
                                       searchQuery,
                                       nPath,                                   startIndex,
                                       this.PostsPerPage,
                                       this.WordsMode,
                                       this.EscapeSpecialChars,
                                       out totalItems);
  10. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    15 Feb 2010
    Link to this post
    How can I specify which index to return results from specifically?

    So at the moment I'm using

    string
    nPath = "CustomIndex";

    Which obviously isnt correct, but I'd like to return only results associated to an index which the search box is not using, is this possible?

     

  11. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    15 Feb 2010
    Link to this post
    Hi Michael Gamlin,

    You need to use PathUtil.GetIndexPhysicalPath which gets the relative path to the segments file of your index. The segments files are stored in App_Data/Search/YOUR_INDEX_NAME_FOLDER.

    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.
  12. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    16 Feb 2010
    Link to this post
    Hello,

    I followed your instructions and attempted to use the paths in the line of code that follows:

    App_Data/Search/CustomIndex


    App_Data/Search/CustomIndex/Index


    string

     

    nPath = PathUtil.GetIndexPhysicalPath("App_Data/Search/CustomIndex/Index");

     


    Both of which returned an invalid index error, could there be an issue where we have multiple sites on the same drive with different directories and I have to be more explicit?
  13. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    16 Feb 2010
    Link to this post
    Hi Michael Gamlin,

    You need to specify the Index catalog only as shown below.

    PathUtil.GetIndexPhysicalPath("PageIndex");


    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.
  14. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    16 Feb 2010
    Link to this post
    I'm having a further issue, when searching for terms, using my custom Search Result control the following error is being displayed:

    Server Error in 'Home/' Application.
    no segments* file found: files:
    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.IO.FileNotFoundException: no segments* file found: files:

    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.

    This only occurs when I use my custom Search Result control, when using the standard one this error does not occur, the only real difference between them is how I override the index that will be searched, rather than using the one specified within the search box control.
  15. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    16 Feb 2010
    Link to this post
    Hi Michael Gamlin,

    The error says that the segment files generated by Lucene search engine in App_Data/Search/YOUR_SEARCH_INDEX cannot be found. Most probably your custom control does not get the index properly.

    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.
  16. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    17 Feb 2010
    Link to this post
    Hello Ivan,

    Thank you for the response I guessed it would be that but can't find anything that stands out within the code, can you see anything specific?

    protected override void CreateChildControls()
            {
                this.Controls.Clear();
                this.InitializeTemplate();
      
                this.Controls.Add(this.custCnt);
                this.custCnt.ResultsList.ItemDataBound += new RepeaterItemEventHandler(ResultsList_ItemDataBound);
                this.custCnt.ResultsList.DataBind();
      
                if (!string.IsNullOrEmpty(Query))
                {
                    string nPath = PathUtil.GetIndexPhysicalPath("Test"); //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;
      
                        bool isValid = this.EscapeSpecialChars ? this.EscapeSpecialChars : ValidateQuery(ref searchQuery, out message);
      
                        if (isValid)
                        {
                            int totalItems;
                            int startIndex = (this.CurrentPage - 1) * this.PostsPerPage;
      
                            try
                            {
                                IList<ResultItem> CustomDataSource = SearchManager.Search(
                                       searchQuery,
                                       nPath,
                                       startIndex,
                                       this.PostsPerPage,
                                       this.WordsMode,
                                       this.EscapeSpecialChars,
                                       out totalItems);
      
                                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.custCnt.ResultStats).EnableViewState = false;
                                this.custCnt.ResultStats.Text = string.Format(this.custCnt.ResultStats.Text, totalItems, qeryTest);
      
                                if (this.AllowPaging)
                                {
                                    this.custCnt.Pager1.SelectedPageChanged += new EventHandler<EventArgs>(Pager_SelectedPageChanged);                                 this.custCnt.Pager1.PageCount = numberOfPages;
                                    this.custCnt.Pager1.SelectedPage = this.CurrentPage;
                                }
      
                                this.custCnt.ResultsList.DataSource = CustomDataSource;
      
                            }
                            catch (Telerik.Lucene.Net.QueryParsers.ParseException ex)
                            {
                                this.custCnt.ResultStats.Text = "strange chars";
                                Log.Exception(ex);
                            }
                        }
                        else
                        {
                            this.custCnt.ResultStats.Text = message;
                        }
                    }
                    else
                    {
                        this.custCnt.ResultStats.Text = String.Format("InvalidIndex", this.IndexCatalogue);
                    }
                }
                else
                {
                    this.custCnt.ResultStats.Text = String.Empty;
                }
            }
  17. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    17 Feb 2010
    Link to this post
    Hello Michael Gamlin,

    Check whether the segment files exist in App_Data/Search/YOUR INDEX FOLDER. The error is thrown by Telerik.Lucene.Net.Index.SegmentInfos which cannot find  segments.gen when you perform a search. We call GetCurrentSegmentGeneration which checks whether the segment files exist. In your case the GetCurrentSegmentGeneration return negative value and the error is thrown.


    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.
  18. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    17 Feb 2010
    Link to this post
    Hello Ivan,

    The file exists, its located within App_Data/Search/CustomSearchIndex/Index/segments.gen

    (I've changed the name of the index since the code I posted just as a test)

    Should the segements.gen be located within the Index folder? Like I said earlier if I use the normal SearchResult control it has no issues.
  19. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    17 Feb 2010
    Link to this post
    Hi Michael Gamlin,

    Send the control and its template so I will run it locally and see what could be the problem.

    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.
  20. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    17 Feb 2010
    Link to this post
    Hello Ivan,

    The support is very much appreciated and I must thank you for your work throughout this process.

    You can find my CustomSearchResultControl project and the associated template in the link below. If you have any queries or would like to clear anything up, just let me know. (Some parts aren't complete yet, such as the title sections, as they're more for cosmestic areas which aren't yet required.)

    CusomSearchResultControl Download
  21. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    17 Feb 2010
    Link to this post
    I would just like to add something to the last post and that is when I create a new search Index and try searching that from within my Custom Search Results Class a new folder is created within App_Data/Search.

    So when I tried to search an Index called Test a folder called E-Sitefinity-WebSites-Home-App_Data-Search-CustomSearchIndex-Index is created with a folder contained in it called Index.

    The file name matches the location of the index is located, but obviously creates a seperate file, is this something you have seen before? I can provide a screenshot if it would be helpful to you.
  22. Ivan Dimitrov
    Ivan Dimitrov avatar
    16072 posts
    Registered:
    16 Jun 2017
    17 Feb 2010
    Link to this post
    Hello Michael Gamlin,

    The problem comes from the highlighted parameter below

    IList<ResultItem> CustomDataSource = SearchManager.Search(
                                       searchQuery,
                                       nPath,
                                       startIndex,
                                       this.PostsPerPage,
                                       this.WordsMode,
                                       this.EscapeSpecialChars,
                                       out totalItems);

    You have to use the index name, but you use the path the the index. I suggest that you should use VS debugger and intellisense in the feature. You cannot just copy - paste from the examples.


    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.
    Answered
  23. Michael
    Michael avatar
    32 posts
    Registered:
    14 Jan 2010
    17 Feb 2010
    Link to this post
    Hello Ivan,

    Thank you, it was an amatuer mistake on my part, but I do appreciate the effort you have put in.

    Thanks
Register for webinar
23 posts, 1 answered