Sitecore Faceting-List and Link Type Fields:Part-2

A second post in the series on Sitecore Faceting, the first post, Sitecore Faceting Novice Learnings was about getting stated with Sitecore Faceting, if you have missed it check it here. This post is about a Sitecore Setting that comes in handy when faceting for List or Link Type fields needs to be implemented.

Are you faceting List (MultiList, TreeList and others) and Link (General Link, DropLink and others) Type Fields and wanted to display the search results on a bucket, faceted by any of these fields? These fields internally stores ID of the referenced item, so if you facet on them you will see IDs being displayed on the search UI.

Below is the list of fields that stores ID of the referenced item in index,
– Checklist
– GroupedDropLink
– MultiList
– TreeList
– TreeListEx
– DropLink
– DropTree
– GeneralLink

Note: DropList and GroupedDropList stores the name of the referenced item in an index so we do not need to worry about them while faceting.

Below screenshot displays how by default the Search UI displays IDs while faceting List and Link Type fields.

IDsDisplaying

Sneaking over the indexes via Luke will also show that the indexes stores the ID of the item and hence it displays the same on the Search UI.

 

Luke-Checklist

 

Luke-MultiList

Content authors will surely come complaining to a developer that they will be happy if they see the actual name (friendly name) of the item being faceted instead of ID.

Sitecore has a lot of settings which allows you to tweak things and configure sitecore your way. I would like to share about a gem (so called setting) for Faceting in this post.

Problem Statement

How to display Friendly Name in Search UI for List & Link fields being used for Faceting?

The Approach

In order to solve above problem I started with googling and the hits that made me interested were,

Sitecore 7 Content Search – Custom Facets on List Fields by Glen McInnis, after going through this article it was not going to help me as it was SOLR and I needed something for Lucene.

FACETS EXPLAINED by Sitecore 7 Development Team, this too didn’t worked for me as these were the steps I already did and the Search UI was displaying IDs for me on the bucket folder for the facets.

SITECORE 7: MAKING GOOGLE PART 2 by Sitecore 7 Development Team, this post seemed promising to me and made me think I would have to define a virtual field and do customization. But this was a lot to do.

It constantly made me think that there should be a simpler way to achieve this hence I discussed with few brilliant brains around me (Kiran Patil and Bhavesh Maniya) who I thought might have worked on faceting. This too didn’t helped me as these guys didn’t worked on faceting for List or Link Type fields.

Brilliant brains have brilliant ideas, Kiran suggested me to look at the sitecore support portal and check if there is a ticket for it. This was a bull’s-eye for me and I found my solution. Marcia Dietrich one of our colleague already had the same problem and was answered to her query by Sitecore Support Team.

The Simplest Solution

So here come the curtain raiser, below setting is used for displaying item name for a list field being faceted on the Search UI.

The comments above this setting does mentions that if you have huge data this might degrade performance so use it wisely.

Setting the value of “BucketConfiguration.ResolveFacetValueToFriendlyName” to “true” in \App_Config\Include\Sitecore.Buckets.config would change the IDs to friendly name and you would have now become a magician for your content authors





FacetName

I am just warming up myself to write the third one in this series of sitecore faceting. If you find it interesting or want to share more about faceting please do comment on this post.

Sitecore Faceting Novice Learnings: Part-1

Sitecore 7 and above versions are really powerful in search capabilities, there are lot of things that can be accomplished. Lucene, Solr, ComputedFields, VirtualFields, Buckets and Faceting has made search very easy in Sitecore.

I have intentionally highlighted “Faceting” above as this is what I am going to blog about in this post. This post is about how you can get started with Faceting in Sitecore.

Task Description

Create a facet for News Category that will be displayed and used to filter results on a bucket folder which contains News Articles.

Here I am demonstrating News Articles which are very common to sites other examples where faceting can be implemented are Products, Employees, Customers, Case Studies and many more.

Creating a Facet

In order to get started with faceting the very first step is to define a facet, you can define a facet at “/sitecore/system/Settings/Buckets/Facets

1)      Select Facets-> Right Click and Insert Facet

Create Facet

2)      Provide Name for the facets in our case it would be “News Category”.

Facet Name

3)      Once the facet is created, there are few important fields that needs to be understood,

Field Usage
Field Name This field should have the name of the field in lower case and should match the field name in your sitecore_master_index. Ideally it would be the field name on your News Article template.

Note: If your field name have spaces replace the space with “_” so for e.g News Article template has “News Category” field, then the field name to be specified in facet should be “news_category”

Global Check this field if you want this facet to appear on all your buckets.Note: If your facet is not global and it should appear on a specific bucket only? Refer to section “Non-Global Facets” of this post to achieve this.

Facet-Fields

 

4) Now go to your bucket folder and search, custom configured facet will appear.

Facet-Results

News Category is a single line text field and “Dealernews” value can be seen faceted in above screen.

News-Item

Non-Global Facet

In most of the cases we will be creating non-global facets as they should be displayed only on specific Buckets and not all over the other sitecore buckets.

1)      To do so first off all uncheck the “Global Facet” field on your custom facet.

2)      Select the bucket on which you want the facet to be applied, in Content Tab -> Go to Indexing Section and look for “Facets” field. Select required facet.

Non-Global-Facet

Below is a code snippet in case if you want to add facets to an item programmatically.

public void AddNewsFacets(ID itemID)
        {
            const string newsCategoryFacet = "{C4788FE1-EF4A-4814-961C-1CF85B9144CA}";
            var item = Sitecore.Context.Database.GetItem(itemID);

            Logger.LogMessage(string.Format("Adding Facets {0}", itemID), this);
            using (new EditContext(item))
            {
                MultilistField fieldfacet = item.Fields["__facets"];
                if (fieldfacet==null)
                {
                    return;
                }
                //clear the values first if any saved in the field
                item.Fields["__Facets"].Value ="";

               //now add the required facets
                fieldfacet.Add(newsCategoryFacet);                
            }
            Logger.LogMessage("Adding TOT Facets Complete", this);
        }

Be tuned on more for Sitecore Faceting! Till then Keep Sitecoring and Sharing

Sitecore8 Logout Bug

I might be “the fewer ones” who got chance to work on an upgrade project from Sitecore 6.6 to Sitecore8. During our initial installation phase when I was playing around with Sitecore8 discovered a bug with the Logout link available at the top right corner of Sitecore Launch Pad.

Sitecore8 Logout

Do you ever logout from Sitecore? I have seen most of the users directly closing the browser, instead of doing it a correct way and logging out. Logging out correctly doesn’t matters if your license covers huge number of logins, however if you have limited logins licensed and users do not logout, often you might come across a message stating maximum number of allowed users has been reached. If you have come across such a message here is a very nice article explaining the solution.

So, you have just logged in Sitecore8 to get a snitch of it and clicked on “Logout” link it comes up with error as shown below.

Sitecore8-Logout-error

Sitecore8-Logout-error

This happens only for the first time when you click on Logout link. Using browser back button and clicking again on Logout will not reproduce this issue. It’s just for the first time in a new browser session.

Sitecore Support has provided a solution for it and that is what I am sharing it here,

1. Backup /Website/Views/Shared/ExperienceExplorerView.cshtml

2. Download ExperienceExplorerView.zip, extract and replace ExperienceExplorerView.cshtml at /Website/Views/Shared folder.

That’s all I have to share in this post, keep Sitecoring and sharing.

Remote Desktop Sitecore Azure Instance

Sitecore Azure is built around Windows Azure cloud services (PaaS) and includes automatic deployment of web servers as well as Microsoft SQL databases. So the point to be noted is does Sitecore supports IaaS? Yes Sitecore supports both the flavours of Windows Azure, hence a sitecore solution can be deployed on either PaaS or IaaS. Also Sitecore and Sitecore Azure should be considered as two different entities and that is where it is said that Sitecore Azure Module is built to support (PaaS) and not IaaS.

For comparing SaaS, IaaS and PaaS you might read through my another post here which will give you a fair bit of details about all the three services provided by Windows Azure.

The reason to write this post is How can we enable Remote Desktop Connection(RDC) to a WebRole that is deployed using Sitecore Azure? As Sitecore Azure only supports PaaS which might make us think that we cannot manage IIS or connect to the Virtual Machine(VM) which gets created during sitecore azure deployment. Well I was also under the same thinking that what benefits do sitecore azure comes with, if we cannot look what’s setup has been made behind my sitecore website. I was totally wrong until I figured out a way to connect to the VM.

So let’s see How RDC can be enabled on a webrole instance for a sitecore azure supported website?

RDC can be enabled via Windows Azure Management Portal but considering after a successful deployment of Sitecore.

1) Login to Windows Azure Management Portal

2) Click Cloud Services, click the name of the cloud service (in our case it is SitecoreCloudTestTestSaCe01Role01ScB28), and then click Configure.

Azure Cloud Service

3) Click Remote.

Azure Remote

Warning: All role instances will be restarted when you first enable Remote Desktop and click OK (checkmark). To prevent a reboot, the certificate used to encrypt the password must be installed on the role.

To prevent a restart, install a certificate and then return to this dialog (see Using Remote Desktop with Azure Roles for more information). If you choose an existing certificate, then a configuration update will be sent to all the instances in the role.

4) In Configure Remote Desktop dialog select Role of you sitecore website,

Specify UserName, New Password, Confirm Password, Select Create a new certificate and lastly the date of expiration of this certificate.

Remote Desktop

Once you click , background process will be initiated.

Configuring RDC

5) Windows Azure Portal will notify on successful configuration of RDC.

Success RDC

6) There might be a thought in your mind now what to do after configuring RDC. How can you get a .rdp file to connect to the Remote Session? Read further…

Now click on INSTANCES tab and select CONNECT, this will allow you to download a .rdp file.

Connect EDC

 

RDP Download

7) You now just need to double click and open the .rdp file in order to remotely connect to the VM. Provide UserName and Password.

Login

8) On successful login you can now access the VM.

VM Login
9) You can also check IIS and the sitecore website deployed.

IIS VM

Hope this would have been a nice read for you! Enjoy Sitecore and keep sharing.

 

Implementing CSS and JS in Sitecore

Cascading Style Sheet (CSS) and JavaScript (JS) are included as a link to a file in websites. Most of the live sitecore solutions also follow the same pattern. Sitecore provides the flexibility to break free from the standard procedures and implement new solutions.

There are different solutions to a single problem and Sitecore being flexible always helps to improve an implemented solution. CSS and JS implementation are no exceptions to it and there are different ways to incorporate them in Sitecore. I have come across few different CSS and JS implementations on Sitecore and would be discussing them in this blog post.

I thought definitely there would be various implementations done by others in Sitecore Community and posted as blogs on the net. My search proved that my thinking was correct and hence I would not discuss all those implementation, instead share those implementations as links so that they can be found under one roof so look out for Nice Read section of this post for all those links.

If you are Sitecore expert you might not find this post helpful as this is something you might have already done, but would suggest to comment on this post so that more different way of implementing CSS and JS can be highlighted.

A) CSS and JS Stored as Items in Sitecore

Templates & Items

1) CSS Template & Item

CSSTemplate

CSSItem

2) JS Template & Item

JSTemplate

JSItem

3) Site Settings Template & Item

SiteSettingsTemplate

SiteSettingItem

Another way to implement StyleSheets and JavaScripts Section is to build them as a separate templates and then inherit SiteSetting template from them. This gives you flexibility in case if you want to place the Javascripts and Stylesheets on other individual templates.

Layouts

1) JS layout code

protected void Page_Load(object sender, EventArgs e){
            this.ReturnJS();

        }
        private void ReturnJS()
        {
            Sitecore.Data.Items.Item currentItem = Sitecore.Context.Item;

    	if (currentItem != null)
                {
                    string script = currentItem.Fields["JS Content"].Value;
                    Response.Clear();
                    Response.ContentType = "text/javascript";
                    Response.Write(script);
                    Response.Flush();
                    //Response.Close();
                    Response.End();
                }
        }

2) CSS layout code

protected void Page_Load(object sender, EventArgs e)
        {
                this.ReturnCSS();
        }

 private void ReturnCSS()
        {
            Sitecore.Data.Items.Item currentItem = Sitecore.Context.Item;

                if (currentItem != null)
                {
                    string css = currentItem.Fields["CSS Content"].Value;
                    Response.Clear();
                    Response.ContentType = "text/css";
                    Response.Write(css);                    
                   Response.End();
                }           
        }

Creating a static Helper method for Linking StyleSheets

Here is a brief dry run of the static method, it gets the Site Settings item and looks for a multi select field “StyleSheets”. Gets the IDs of the selected StyleSheets and based on their names differentiate them for different media (print, screen and all). Browser specific StyleSheets are also accounted and rendered.

This method builds the link tag and finally adds it to the header of the page which should be marked with runat = ”server” attribute.

public static void SetupStylesheets(Page page, Item siteSettingItem)
        {
            Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions();
            try
            {
                if (siteSettingItem != null)
                {
                    String[] stylesheetIDs = null;
                    if (!string.IsNullOrEmpty(siteSettingItem["Stylesheets"]))
                    {
                        stylesheetIDs = siteSettingItem["StyleSheets"].Split(new char[] { '|' });
                        //set the options for the item URL
                        urlOptions.AlwaysIncludeServerUrl = true;
                        urlOptions.AddAspxExtension = true;

                        foreach (string ids in stylesheetIDs)
                        {
                            if (!string.IsNullOrEmpty(ids))
                            {
                                Sitecore.Data.Items.Item item = Sitecore.Context.Database.GetItem(ids);
                                if (item.Template.Name.ToLower() == "css")
                                {
                                    HtmlLink link = new HtmlLink();
                                    LiteralControl ltrl = new LiteralControl();

                                    link.Attributes.Add("type", "text/css");
                                    link.Attributes.Add("rel", "stylesheet");
                                    if (item.Name.ToLower() == "print")
                                    {
                                        link.Attributes.Add("media", "print");
                                    }
                                    else
                                    {
                                        if (item.Name.ToLower() == "mobile")
                                        {
                                            link.Attributes.Add("media", "all");
                                        }
                                        else
                                        {
                                            link.Attributes.Add("media", "screen");
                                        }
                                    }
                                    link.Attributes.Add("href", Sitecore.Links.LinkManager.GetItemUrl(item, urlOptions).Replace(".aspx", ".css"));

                                    if (item.Name.ToLower() == "ie6")
                                    {
                                        ltrl.Text = "";
                                        if (page.Header.Controls.Count > 0)
                                        {
                                            page.Header.Controls.AddAt(4, ltrl);
                                        }
                                        else
                                        {
                                            page.Header.Controls.Add(ltrl);
                                        }
                                    }
                                    else if (item.Name.ToLower() == "ie7")
                                    {
                                        ltrl.Text = "";
                                        if (page.Header.Controls.Count > 0)
                                        {
                                            page.Header.Controls.AddAt(4, ltrl);
                                        }
                                        else
                                        {
                                            page.Header.Controls.Add(ltrl);
                                        }
                                    }
                                    else
                                    {
                                        if (item.Name.ToLower() == "mobile")
                                        {
                                            page.Header.Controls.Add(link);
                                        }
                                        else
                                        {
                                            page.Header.Controls.Add(link);
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Debug(ex.Message, ex);
                throw ex;
            }
            finally
            {
                urlOptions = null;
            }
        }

Creating a static Helper method for attaching JavaScript

public static void SetupJavaScripts(Page page, Item siteSettingItem)
        {
            Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions();
            urlOptions.AlwaysIncludeServerUrl = true;
            urlOptions.AddAspxExtension = true;

            if (siteSettingItem != null)
            {

                String[] jsIDs = null;
                if (!string.IsNullOrEmpty(siteSettingItem["javascripts"]))
                {
                    jsIDs = siteSettingItem["javascripts"].Split(new char[] { '|' });

                    //set the options for the item URL
                    urlOptions.AlwaysIncludeServerUrl = true;
                    urlOptions.AddAspxExtension = true;

                    foreach (string ids in jsIDs)
                    {
                        if (!string.IsNullOrEmpty(ids))
                        {
                            Sitecore.Data.Items.Item js = Sitecore.Context.Database.GetItem(ids);
                            if (js.TemplateID == TemplateIds.Templates.JavaScript)
                            {
                                HtmlGenericControl script = new HtmlGenericControl("script");
                                script.Attributes.Add("type", "text/javascript");
                                script.Attributes.Add("language", "javascript");
                                script.Attributes.Add("src", Sitecore.Links.LinkManager.GetItemUrl(js, urlOptions).Replace(".aspx", ".js"));
                                page.Header.Controls.Add(script);
                            }
                        }
                    }
                }
            }
        }

Calling Helper methods from Layout

protected void Page_Init(object sender, EventArgs e)
        {
            Item siteSetting = Helper.GetSiteSettings();
            Helper.SetupJavaScripts(this, siteSetting);
            Helper.SetupStylesheets(this, siteSetting);
}

Advantages

– Flexibility to Content Authors for making amends to CSS and JS files and publish them.
– CSS and JS management gets easy as Developers involvement is not required for deployment and that too on different environments.

Disadvantages

– Utmost care needs to be taken by content authors otherwise wrongly made changes to CSS and JS can have adverse look and feel effect on the site.
– Changes done in CSS and JS might not reflect immediately if Sitecore Cache is not updated.
– Performance of the site might degrade as CSS and JS are now items in sitecore as compared to linking the files physically.

B) CSS and JS Stored as Media Items in Sitecore

Storing CSS and JS as Media items in sitecore gives one advantage over the previous implementation, content authors or front end developers can directly upload the files into media library without the hassle of copy pasting the content of these files into sitecore fields.

Media item approach again can be implemented in two ways where the HTML markup for tags can be static or dynamically generated from code.

Static inclusion of <link> and <script> tag in layouts

Depending on how much code one want to write the layouts can contain the tags as follows,

<script type="text/javascript" src="/~/media/JScripts/jquerymin.js"></script>	

<link href="/~/media/StyleSheets/style.css" rel="stylesheet" type="text/css" />

Layout

style

The point to consider for inclusion of static tags is, a deployment would be needed for the first time whenever a new file is introduced or a file’s reference is to be removed

Dynamic inclusion of <link /> and <script> tag in layouts

For this approach upload CSS and JS files in media library, select the media library files on site setting items and use the below code to link the media items.

Note: CSS and JS files will be linked with .ashx extension still it will not cause any problems for these files to be rendered correctly.

public static void SetupMediaStylesheets(Page page, Item siteSettingItem)
        {
            Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions();
            try
            {
                if (siteSettingItem != null)
                {
                    String[] stylesheetIDs = null;
                    if (!string.IsNullOrEmpty(siteSettingItem["Stylesheets"]))
                    {
                        stylesheetIDs = siteSettingItem["StyleSheets"].Split(new char[] { '|' });
                        //set the options for the item URL
                        urlOptions.AlwaysIncludeServerUrl = true;
                        urlOptions.AddAspxExtension = true;

                        foreach (string ids in stylesheetIDs)
                        {
                            if (!string.IsNullOrEmpty(ids))
                            {
                                Sitecore.Data.Items.Item item = Sitecore.Context.Database.GetItem(ids);

                                HtmlLink link = new HtmlLink();
                                LiteralControl ltrl = new LiteralControl();

                                link.Attributes.Add("type", "text/css");
                                link.Attributes.Add("rel", "stylesheet");
                                if (item.Name.ToLower() == "print")
                                {
                                    link.Attributes.Add("media", "print");
                                }
                                else
                                {
                                    if (item.Name.ToLower() == "mobile")
                                    {
                                        link.Attributes.Add("media", "all");
                                    }
                                    else
                                    {
                                        link.Attributes.Add("media", "screen");
                                    }
                                }
                                link.Attributes.Add("href", Sitecore.StringUtil.EnsurePrefix('/', Sitecore.Resources.Media.MediaManager.GetMediaUrl(item)));

                                if (item.Name.ToLower() == "ie6")
                                {
                                    ltrl.Text = "";
                                    if (page.Header.Controls.Count > 0)
                                    {
                                        page.Header.Controls.AddAt(4, ltrl);
                                    }
                                    else
                                    {
                                        page.Header.Controls.Add(ltrl);
                                    }
                                }
                                else if (item.Name.ToLower() == "ie7")
                                {
                                    ltrl.Text = "";
                                    if (page.Header.Controls.Count > 0)
                                    {
                                        page.Header.Controls.AddAt(4, ltrl);
                                    }
                                    else
                                    {
                                        page.Header.Controls.Add(ltrl);
                                    }
                                }
                                else
                                {
                                    if (item.Name.ToLower() == "mobile")
                                    {
                                        page.Header.Controls.Add(link);
                                    }
                                    else
                                    {
                                        page.Header.Controls.Add(link);
                                    }
                                }

                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Log.Debug(ex.Message, ex);
                throw ex;
            }
            finally
            {
                urlOptions = null;
            }
        }
public static void SetupMediaJavaScripts(Page page, Item siteSettingItem)
        {
            Sitecore.Links.UrlOptions urlOptions = new Sitecore.Links.UrlOptions();
            urlOptions.AlwaysIncludeServerUrl = true;
            urlOptions.AddAspxExtension = true;

            if (siteSettingItem != null)
            {

                String[] jsIDs = null;
                if (!string.IsNullOrEmpty(siteSettingItem["javascripts"]))
                {
                    jsIDs = siteSettingItem["javascripts"].Split(new char[] { '|' });

                    //set the options for the item URL
                    urlOptions.AlwaysIncludeServerUrl = true;
                    urlOptions.AddAspxExtension = true;

                    foreach (string ids in jsIDs)
                    {
                        if (!string.IsNullOrEmpty(ids))
                        {
                            Sitecore.Data.Items.Item js = Sitecore.Context.Database.GetItem(ids);
                            HtmlGenericControl script = new HtmlGenericControl("script");
                            script.Attributes.Add("type", "text/javascript");
                            script.Attributes.Add("language", "javascript");
                            script.Attributes.Add("src", Sitecore.StringUtil.EnsurePrefix('/', Sitecore.Resources.Media.MediaManager.GetMediaUrl(js)));
                            page.Header.Controls.Add(script);

                        }
                    }
                }
            }
        }

C) Link to file statically

Being a beginner in sitecore implementations one would always stick to the standard way of adding the CSS and JS using

<link /> and

<script> tags respectively directly on the layout files.

There is no harm including files physically, it’s just that the requirements decides what should one implement a dynamic solution or a static one.

Nice reads

–       Building a Sitecore Base Page Template

–       Managing CSS Files in Sitecore by Mark Graber

–       Managing CSS in the Sitecore Media Library

Sitecore Community Events Calendar

We never want to miss an important event in our life and so we always note them down somewhere on a calendar whether it be online or on a paper. With lot of things happening around us we certainly like to stay organized, plan efficiently and hit those important dates. With calendars now available on mobile and internet we have a choice to interact with them anywhere. I am no exception to a person nowadays using such calendars.

It’s really a luck that I am working on Sitecore and that too when the Sitecore Community is blossoming. Tracking all Sitecore Community Events gets me on the edge of knowledge and updated so I always pin and try to follow the events. The problem was, I have to visit different sites, engage on social media to know about the Sitecore events. This made me thought why can’t I have all Sitecore Community Events noted at one place. Are you thinking on the same line?

Do you want to keep up with the latest Sitecore Events going on near you or world wide? A webinar, A Symposium, A Sitecore User Group Meet or Hackathon. You will find all the events at one place on this calendar. Check Sitecore Community Event Calendar built using Outlook.com Calendar

Feature rich Outlook Calendar has allowed me to share this calendar in various formats,

1)      View in a Browser: http://goo.gl/5Ybe8W

2)      Import into another calendar applications (ICS): WebCal

3)      View in a feed reader(XML): http://goo.gl/Yt1axQ

You can even import this calendar to your Microsoft office outlook using “From Internet” option.

outlook calendar

Sitecore Community Events Widget is also available in case if you wish to embed it on your blog or website. Use the following embed code,

<iframe width=”100%” frameborder=”0″ border=”0px” style=”width: 28%; height: 505px;border:0px;” scrollbars=”no” src=”http://techitpro.com/sitecorefeeds/SitecoreEventsWidget.aspx”></iframe>

Sitecore Event Widget

Sitecore Azure Install Management Certificate Bug

This post, “Sitecore Azure install management certificate bug” contains information and resolution about an installation error received while creating a new environment via Sitecore Azure module. The issue is related to generation of “.publishsettings” file.

One of my colleague Shivam Barve faced this issue while he was trying to have his hands on Sitecore Azure installation. Trying to generate .publishsettings via “Install management certificate”, he was not able to download the file from Install Management certificate dialog.

Sitecore-Azure-PublishSettings

After having his head around with “This page can’t be displayed” error.

Certificate error

I was called in for a helping help. Looking at the error I discovered that the url that is being referred for generation of .publishsetting file was incorrect. It was still using older “https://windows.azure.com” url, but Microsoft has already updated the Azure management portal to “https://manage.windowsazure.com/”. So earlier, for generation of .publishsetting file the url was like “https://windows.azure.com/download/publishprofile.aspx” after new Azure portal it is now https://manage.windowsazure.com/publishsettings/.

I was aware of few knowledge base post for sitecore azure hence visited “Error when installing management certificate for Sitecore Azure” article which explains about two options for generating the .publishsetting file.

Option A did help us generating the .publishsettings file but when we tried uploading it in Sitecore azure we were having “Failed to find certificate in publishsetting file” error.

Sitecore-Azure-Error4

Now the last card that can rescue us was sitecore support, reply from sitecore support (specifically Yuriy Yurkovsky, thanks to him for providing the solution) agreed that it is a bug for the current module version. Microsoft uses a new PublishSettings schema version in new management portal, and this version is incompatible with current module of sitecore azure. For generating .publishsettings file based on old schemaversion we were asked to use the following url.

https://manage.windowsazure.com/PublishSettings/index?client=&schemaVersion=1.0

Bingo!! That did helped us for generating the correct .publishsettings file.

Further googling about the schema version change and comparing the old and new .publishsettings file I discovered the following change.

publishsettings schema2.0

As highlighted in above image the new publishsetting file has an attribute  SchemaVersion=”2.0″. So if your file contains this attribute it will not work with sitecore azure module. The old publishsetting file looks like,

publishsetting schema

Sitecore support now has reported this as a bug and will notify once the bug is resolved. Oh! Are you worried how will you be notified for the issue resolution? I will update this post once the update is released for Sitecore Azure module. Alternatively you can also keep watch on Sitecore Azure Module page at SDN. Till then keep watching this space and keep sharing sitecore knowledge!

Sitecore has now come up with an alternate solution for fixing this issue check the knowledge base article, “Error installing a management certificate in Sitecore Azure when using the 2.0 format of the publish settings file

CustomItemGenerator – Raw Vs Text value

Sitecore community is growing and there are so many market place modules, I came across one such gem from the market place “Custom Item Generator” will refer as CIG in the rest of the post, CIG creators also refer it as “CIG”. In this post I am not going to describe introduction of Custom Item Generator, how CIG can be configured? etc etc… All basic information related to CIG can be found at,

–          Marketplace CIG

–          Custom Item Generator

–          Custom Item Generator: A Simple Example

–          Custom Item Generator: Customization

Why I am writing this post?

Purpose of writing this post is to compare usage of FieldName.Text and FieldName.Raw properties.

I was facing this particular issue where I was not able to see rendered YouTube video in “Page Editor” mode. I was creating a sublayout that should render a YouTube Video and it should also be edited via page editor. The video was rendered in an iFrame where in the src attribute should point to the video on YouTube.

At first, I thought it would be a page editor issue and it might not render content from iFrame. So tried placing simple html iFrame tag without any dynamic attributes assignments from code behind and it was rendering the video correctly.

The same issue I was facing with items in the dropdown where in the <input> tags were rendered instead of the names of the items.

Custom Item Generator - 1

I debugged my code and with help of quick watch in visual studio found that FieldName.Text and FieldName.Raw both are returning different values. This made me interested as to why FieldName.Text provides html tag and not only the actual value.

Looking further at the documentation of CIG I found below explanation on CIG blog which suggested the usage of the .Text and .Raw properties.

  • FieldName.Text – This will access the field through the Sitecore field renderer, in most cases where you are displaying a field’s content on the front end you would want to use.
  • FieldName.Raw – This will return the underlying value that is being stored in the field.

Digging further and making use for RedGate Reflector I figured out that .Text calls indirectly FieldRenderer.Render.

public string Text
{
    get
    {
        return base.Rendered;
    }
}

Extract from BaseCustomField

public string Rendered
{
    get
    {
        if (this.field == null)
        {
            return string.Empty;
        }
        return FieldRenderer.Render(this.item, this.field.InnerField.Name);
    }
}

So the conclusion is if you want to render a general link field or an image field and would also like to have page editor support use FieldName.Text. If your requirements are content should not be edited via page editor as was in my case for dropdown and iFrame, make use of FieldName.Raw.

If you are interested reading further for the difference between raw and rendered values check this blog post “RAW VS RENDERED FIELD VALUES” written by Martina.

Sitecore Media Item download

Looking for a code that helps you download Media items from sitecore? This post might help you.

Based on a project requirement I was asked to work on a functionality for having a download brochure drop down. A thought might have come to your mind why a drop down for downloading brochures, well my mind too said “what a wired request?”. Why not we just display links for the brochures. But we need to follow the designs and respect client’s requirements. So I created a drop down which displayed items that comes from a multilist field.
Initially I had the media item’s url as the options value for my drop down, but then came across GetMediaStream() method which does the work for getting a media item into a stream so I tweaked my approach and passed item ID in the value for options.

protected void Page_Load(object sender, EventArgs e)
{
  Item currentItem = Sitecore.Context.Item;
  if (currentItem.Fields["MultiListField"] == null) return;

  MultilistField mltFld = currentItem.Fields["MultiListField"];
  foreach (var item in mltFld.GetItems())
  {
                ddlDownloadBrochure.Items.Add(new ListItem(item.Name, item.ID.ToString()));
  }
}
protected void ddlDownloadBrochure_SelectedIndexChanged(object sender, EventArgs e)
{
  if (ddlDownloadBrochure.SelectedValue == null || ddlDownloadBrochure.SelectedValue == "0") return;

  PromptDownloadBrochure(ddlDownloadBrochure.SelectedValue);
}

Below is the method that will fetch all the details of media item, including name, extension and push it back as response.

private void PromptDownloadBrochure(string mediaID)
        {
            ID id = new ID(mediaID);
            if (id.IsNull)
                return;

            MediaItem mediaItem = Sitecore.Context.Database.Items.GetItem(id);
            if (mediaItem != null)
            {
                Stream stream = mediaItem.GetMediaStream();
                long fileSize = stream.Length;
                byte[] buffer = new byte[(int)fileSize];
                stream.Read(buffer, 0, (int)stream.Length);
                stream.Close();
                Response.Clear();
                Response.CacheControl = "public";
                Response.ContentType = "application/octet-stream";

                Response.AddHeader("content-disposition", "attachment; filename=" + mediaItem.Name + "." + mediaItem.Extension);
                Response.Cache.SetCacheability(HttpCacheability.NoCache);
                Response.BinaryWrite(buffer);
                Response.End();
            }
        }

You can allow the download on a button click or any other asp.net control which does a post back.

End of string expected at position

End of string expected at position” if you are facing this error definitely you are working on sitecore query. There are lot of articles and blogs available on sitecore query. I usually refer to these master pieces “CheatSheet” and “Sitecore Query Syntax” when I get stuck with sitecore query, it’s like a shorthand revision note that we use during our exams. CheatSheet also provides information about escaping xpath keywords and much more.

Now let’s move back to the problem statement, my sitecore query was working fine for few items and was giving above error for few other items. I compared the items and concluded that it had to do with the xpath keywods like “and” and “or” in the item names. To be cent percent sure, I tried the query with xpath builder tool in developer center and had the same error displayed.

After googling found on stackoverflow and other blogs,found that this error arises in some other situations also, hence thought why not to bring all the solutions under one roof so here I will mention all the different issues and solutions. Am I missing something? comment on this post and I will include that too.

Symbol # comes to our rescue and is used as an escape sequence character. Hence the solution to most of the problems related to sitecore query can be resolved using it.

1) Query contains reserved keywords

ancestor and child descendant
div false following mod
or parent preceding self
true xor

So if your query is like

sitecore/content/Home/News and Events/*

or

sitecore/content/Home/News/following up with media/*

it will yield you end of string expected error.

Solution: Reframe your query using # as below

sitecore/content/Home/#News and Events#/*

or

sitecore/content/Home/News/#following up with media#/*

A C# approach to sitecore query might be,

var childItem = Sitecore.Context.Database.Select(string.Format(“{0}//*”),Sitecore.Context.Item.Paths.FullPath);

The above code can throw error if fullpath contains keywords. The solution I used was to build a function to escape these keywords something like,

public string EscapeXPathKeywords(string query)
        {
            //Escape xpath keywords from sitecore query  
            return query.ToLower().Replace(" and ", " #and# ").Replace(" or ", " #or# ")
                .Replace(" true ", "#true# ").Replace(" false ", " #false# ")
                .Replace(" div ", " #div# ").Replace(" mod ", " #mod# ").Replace(" - ", " #-# ")
                .Replace("-", " #-# ").Replace("$", " #$# ");
        }
var childItem = Sitecore.Context.Database.Select(string.Format(“{0}//*”), EscapeXPathKeywords (Sitecore.Context.Item.Paths.FullPath));

Did you observed spaces before and after the keywords in string.Replace()? No? well those spaces needs to be there else the replace function will replace your string as

Sitec#or#e/content/Home/News #or# Events/

2) Item name starts with digit or contains dash(“-“)

If your query is something like

sitecore/content/Home/News and Events/2014/*

or

sitecore/content/Home/News-Events/*

The solution is similar and use # or write a function similar to EscapeXPathKeyword.

Thinking to write few more blogs on sitecore query and fast query till then keep reading and sharing sitecore knowledge.