Surendra Sharma

Surendra Sharma

Search This Blog

Thursday, September 10, 2015

One line of C# code to check item's base templates in Sitecore



As we know Sitecore allow both multiple and multi-level inheritance. If we template is inherited from multiple and multi-level inheritance then it’s very cumbersome to check the base template by using code. However here is simple scenario with only line of code to achieve it.

For example, suppose you have below content tree with parent node is Fruit

·         Fruits
o    Apple 1 : base template Apple
o    banana 1 : base template Banana
o    Apple 2 : base template Apple
o    Mango 1 : base template Mango
o    Mango 2 : base template Mango
o    Green Apple 1: base template Apple, Green Apple

Now if anyone want only items which are of Apple types then we can achieve it in single line of code as 

rptFruit.DataSource = ((Item)Fruits).Children.Where(x => x.Template.BaseTemplates.Any(y => y.ID.Equals(AppleTemplateId)));

If you are trying to access children of any item and want to access only those children items which are inherited from one particular type of template then use LINQ as <item>.Template.BaseTemplates.Any() method.
 
Please leave your comments or share this code if it’s useful for you.

Thursday, August 20, 2015

Step by Step guide to implement Lucene Search in Sitecore

Do you want to implement Lucene search in Sitecore and unable to get where to start exactly? Fuck all those theory on internet and refer this straight forward guide.

Rename “\Website\App_Config\IncludeSitecore.ContentSearch.Lucene.Index.Master.config” to “IncludeSitecore.ContentSearch.Lucene.Index.Surendra.config

Open and do the following highlighted config changes. Basically add your template IDs which do you want to show as a search result

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <contentSearch>
      <configuration type="Sitecore.ContentSearch.ContentSearchConfiguration, Sitecore.ContentSearch">
        <indexes hint="list:AddIndex">
          <index id="Surendra" type="Sitecore.ContentSearch.LuceneProvider.LuceneIndex, Sitecore.ContentSearch.LuceneProvider">
            <param desc="name">$(id)</param>
            <param desc="folder">$(id)</param>
            <!-- This initializes index property store. Id has to be set to the index id -->
            <param desc="propertyStore" ref="contentSearch/indexConfigurations/databasePropertyStore" param1="$(id)" />
            <configuration ref="contentSearch/indexConfigurations/defaultLuceneIndexConfiguration">
              <include hint="list:IncludeTemplate">
                <Template1>{11111111-2222-3333-4444-123456789123}</Template1>
                <Template2>{11111111-2222-3333-4444-123456789124}</Template2>
                <Template3>{11111111-2222-3333-4444-123456789125}</Template3>
                <Template4>{11111111-2222-3333-4444-123456789126}</Template4>
                <Template5>{11111111-2222-3333-4444-123456789127}</Template5>
              </include>
              <IndexAllFields>true</IndexAllFields>
            </configuration>
            <strategies hint="list:AddStrategy">
              <!-- NOTE: order of these is controls the execution order -->
              <strategy ref="contentSearch/indexConfigurations/indexUpdateStrategies/onPublishEndAsync" />
            </strategies>
            <!--<commitPolicyExecutor type="Sitecore.ContentSearch.CommitPolicyExecutor, Sitecore.ContentSearch">
              <policies hint="list:AddCommitPolicy">
                <policy type="Sitecore.ContentSearch.TimeIntervalCommitPolicy, Sitecore.ContentSearch" />
              </policies>
            </commitPolicyExecutor>-->
            <locations hint="list:AddCrawler">
              <crawler type="Sitecore.ContentSearch.SitecoreItemCrawler, Sitecore.ContentSearch">
                <Database>master</Database>
                <Root>/sitecore/content/Surendra/Homepage</Root>
              </crawler>
            </locations>
            <!--
            <shardingStrategy type="Sitecore.ContentSearch.LuceneProvider.Sharding.LucenePartitionShardingStrategy, Sitecore.ContentSearch.LuceneProvider">
              <param desc="shardDistribution">4</param>
            </shardingStrategy>
            -->

            <!--
            <shardFolders hint="raw:AddShardFolderPath">
              <shard shardName="shard1" shardRootFolderPath="c:\Data\Indexes" />
              <shard shardName="shard2" shardRootFolderPath="c:\Data\Indexes" />
              <shard shardName="shard3" shardRootFolderPath="c:\Data\Indexes" />
            </shardFolders>
            -->
          </index>
        </indexes>
      </configuration>
    </contentSearch>
  </sitecore>
</configuration>

Open Sitecore Desktop version -> Control Panel -> Indexing – Indexing Manager -> Checked only “Surendra” Instance -> Next -> Finish [There must be some units processed at this stage.]

Goto IIS and recycle application pool of your site.

Create Search content item and set Search control layout with this content item.

Add below HTML and C# code in this Search page

<asp:TextBox runat="server" ID="txtsearch" ></asp:TextBox>

                <asp:Button runat="server" ID="btnSearch" Text="Search" OnClick="btnSearch_Click" CssClass="searchbtn" />



            <ul>
                <asp:Repeater ID="rptEvents" runat="server">
                    <ItemTemplate>
                        <asp:HyperLink NavigateUrl="<%# Sitecore.Links.LinkManager.GetItemUrl((Item)Container.DataItem) %>" runat="server">
                            <li>
                                <strong>
                                    Title
                                   Write your HTML code here
                                </strong>
                            </li>
                        </asp:HyperLink>

                    </ItemTemplate>
                </asp:Repeater>
            </ul>

using Lucene.Net.Analysis.Standard;
using Lucene.Net.Analysis;
using Sitecore.ContentSearch;
using Sitecore.ContentSearch.SearchTypes;
using Sitecore.Data.Items;

        /// <summary>
    /// Search Page
    /// </summary>
    public partial class Search : System.Web.UI.UserControl
    {
        #region Properties

        public string LeftPartClass { get; set; }

        private int RowCount
        {
            get
            {
                int result = 0;
                if (ViewState["RowCount"] != null)
                {
                    result = (int)ViewState["RowCount"];
                }
                return result;
            }
            set
            {
                ViewState["RowCount"] = value;
            }
        }

       
        #endregion

        #region Page Load

        /// <summary>
        /// Page Load
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void Page_Load(object sender, EventArgs e)
        {
            LeftPartClass = "Show";

            if (!IsPostBack)
            {

                RowCount = 0;


                if (Request.QueryString != null && Request.QueryString.Count > 0 && !string.IsNullOrEmpty(Request.QueryString["q"]))
                {
                    Session["q"] = Request.QueryString["q"].Trim();
                }

                SearchContent(Session["q"], 10, 0);
            }
            else
            {
                plcPagingTop.Controls.Clear();
                plcPagingBottom.Controls.Clear();
                CreatePagingControl();
            }   

        }

        #endregion

        #region ASP.NET Event

        /// <summary>
        /// Search button
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        protected void btnSearch_Click(object sender, EventArgs e)
        {
            Session["q"] = txtsearch.Text.Trim();

            Response.Redirect(Request.UrlReferrer.AbsolutePath);
        }

        #endregion

        #region Paging Section

        /// <summary>
        /// Create Page number
        /// </summary>
        private void CreatePagingControl()
        {
            //Get total pages
            int totalPage = (RowCount / 10) + 1;

            //Check initiliase boundry coditions
            if (totalPage == 1)
            {
                totalPage = 0;
            }

            //Check last boundry coditions
            if(RowCount % 10 == 0)
            {
                totalPage = RowCount / 10;
            }

            GeneratePageNumber(totalPage, "Top", plcPagingTop);
            GeneratePageNumber(totalPage, "Bottom", plcPagingBottom);
        }

        /// <summary>
        /// Generate page number for all pager
        /// </summary>
        /// <param name="totalPage"></param>
        /// <param name="pagerLocation"></param>
        /// <param name="placeHolder"></param>
        private void GeneratePageNumber(int totalPage, string pagerLocation, PlaceHolder placeHolder)
        {
            for (int iCounter = 0; iCounter < totalPage; iCounter++)
            {
                LinkButton lnk = new LinkButton();
                lnk.Click += new EventHandler(lbl_Click);
                lnk.ID = "lnkPage" + pagerLocation + (iCounter + 1).ToString();
                lnk.Text = (iCounter + 1).ToString();
               
                placeHolder.Controls.Add(lnk);
               
                Label spacer = new Label();
                spacer.ID = "lblSpace" + pagerLocation +(iCounter + 1).ToString();
                spacer.Text = "&nbsp;";
                placeHolder.Controls.Add(spacer);
            }
        }

        /// <summary>
        /// Show selected page number search
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void lbl_Click(object sender, EventArgs e)
        {
            LinkButton lnk = sender as LinkButton;
            int currentPage = int.Parse(lnk.Text);
            hdnPageNum.Value = currentPage.ToString();
            int take = currentPage * 10;
            int skip = currentPage == 1 ? 0 : take - 10;
            SearchContent(Session["q"], take, skip);
        }

        #endregion

        #region Search Block

        /// <summary>
        /// get search content and render accordingly
        /// </summary>
        /// <param name="input"></param>
        private void SearchContent(string input, int take, int skip)
        {
            if (string.IsNullOrEmpty(input))
            {
                if (Request.QueryString != null && Request.QueryString.Count > 0 && !string.IsNullOrEmpty(Request.QueryString["q"]))
                {
                    Session["q"] = Request.QueryString["q"].Trim();
                    input = Request.QueryString["q"].Trim();
                }
                else
                {
                    LeftPartClass = "Hide";
                    return;
                }
            }

            ltMessage.Text = string.Format("0 results found for <strong>\"{0}\"</strong>", input);

            string textToSearch = input;
            List<string> terms = TokenizeByStandardAnalyzer(textToSearch);

            ISearchIndex index = Sitecore.ContentSearch.ContentSearchManager.GetIndex("Surendra");

            using (IProviderSearchContext context = index.CreateSearchContext())
            {
                var expression = BuildSearchExpression(terms);

                var query = context.GetQueryable<SearchResultItem>().Where(expression);

                List<SearchResultItem> results = query.ToList();

                if (results.Count > 0)
                {
                    var searchItemList = results.Select(x => Sitecore.Context.Database.GetItem(x.ItemId)).Select(x => new
                    {
                        DisplayName = x.DisplayName,
                        ItemURL = Sitecore.Links.LinkManager.GetItemUrl(x)
                    }).Distinct().OrderBy(x=> x.DisplayName).ToList();

                    int totalRecords = searchItemList.Count();

                    var pagingRecords = from p in searchItemList.ToList()
                       .Take(take)
                       .Skip(skip)
                                        select p;

                    PagedDataSource page = new PagedDataSource();
                    page.AllowCustomPaging = true;
                    page.AllowPaging = true;
                    page.DataSource = pagingRecords;
                    page.PageSize = 10;

                    rptEvents.DataSource = page;
                    rptEvents.DataBind();

                    if (!IsPostBack)
                    {
                        RowCount = totalRecords;
                        CreatePagingControl();
                    }

                    int toRecords = (totalRecords < take) ? totalRecords : take;
                    ltMessage.Text = string.Format("<strong>{0}-{1}</strong> of about <strong>{2}</strong> results found for <strong>\"{3}\"</strong>",
                        skip + 1, toRecords, totalRecords, input);

                }
            }
        }

        /// <summary>
        /// Builds a search Expression for querying the search index
        /// </summary>
        /// <param name="terms">IEnumerable List of search terms</param>
        /// <returns></returns>
        System.Linq.Expressions.Expression<Func<Sitecore.ContentSearch.SearchTypes.SearchResultItem, bool>> BuildSearchExpression(IEnumerable<string> terms)
        {
            var expression = Sitecore.ContentSearch.Linq.Utilities.PredicateBuilder.False<SearchResultItem>();
            return terms.Aggregate(expression, (current, term) => Sitecore.ContentSearch.Linq.Utilities.PredicateBuilder.Or(current, item => item.Content.Contains(term) || item.Name.Contains(term)));
        }

        /// <summary>
        /// Tokenizes the search term string in order to allow multi term search
        /// </summary>
        /// <param name="fieldValue">Search Field Value</param>
        /// <returns></returns>
        List<string> TokenizeByStandardAnalyzer(string fieldValue)
        {
            var analyzer = new StandardAnalyzer(Lucene.Net.Util.Version.LUCENE_30);
            TokenStream stream = analyzer.TokenStream("dummy", new System.IO.StringReader(fieldValue));
            var attribute = stream.AddAttribute<Lucene.Net.Analysis.Tokenattributes.ITermAttribute>();
            var list = new List<string>();
            while (stream.IncrementToken())
            {
                string term = attribute.Term;
                list.Add(term);
            }
            stream.End();
            return list;
        }

        #endregion

    }

Please leave your comments or share this tip if it’s useful for you.