Surendra Sharma

Surendra Sharma

Search This Blog

Friday, April 24, 2015

How to create Page Not Found in Sitecore

In every Sitecore application, if end user type some page name that is not exist then we need to redirect user to some custom page which inform user that requested page is not available.

Here are the steps for it.

·         Create template, layout and content item for Page not found.
·         Write below code in your project

namespace MyProject.CodeFiles
{
    /// <summary>
    /// 404 class
    /// </summary>
    public class Page404Resolver : Sitecore.Pipelines.HttpRequest.HttpRequestProcessor
    {
        public override void Process(Sitecore.Pipelines.HttpRequest.HttpRequestArgs args)
        {
            if (Sitecore.Context.Item != null || Sitecore.Context.Site == null || Sitecore.Context.Database == null)
            {
                return;
            }

            // If current item not available in Sitecore, then
            if (Sitecore.Context.Item == null)
            {
                Sitecore.Diagnostics.Log.Info("Page404Resolver=" + System.Web.HttpContext.Current.Request.Url, this);

                // Find an error-page item and set it to context Item
                Item item404 = args.GetItem(new ID("{XXXXX1D2-8CDB-4461-93CE-501905DDSSSS}"));
                if (item404 != null)
                {
                    Sitecore.Context.Item = item404;
                    Sitecore.Context.Items["is404"] = "true";
                    Sitecore.Diagnostics.Log.Info("CUSTOM ERROR HANDLER: 404 :  Item is not null - Setting Context item to 404 page", this);
                }
            }
        }
    }
}


·         Open web.config file and add this class just below ItemResolver line of pipeline section

<processor type="Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel"/>
<processor type="MyProject.Web.Present.CodeFiles.Page404Resolver, MyProject.Web.UI"/>

·         Implement below code in page load section of File Not Found page. Keep response status as 404 and also set status of response.

    public partial class NotFound : System.Web.UI.UserControl
    {
        protected void Page_Load(object sender, EventArgs e)
        {
                if (Sitecore.Context.Items["is404"].Equals("true"))
                {
                    try
                    {
                        Response.StatusCode = 404;
                        Response.TrySkipIisCustomErrors = true;
                        Response.StatusDescription = "File not found";
                        //Response.End();
                    }
                    catch (Exception ex)
                    {
                        // Log error
                    }
                }
            }
        }

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

Thursday, April 23, 2015

How to create error page in Sitecore


In every Sitecore application, you have to create error page. Error can be occurred at any time anywhere in application [We developers are always right. Errors are always due to incorrect contents entered by content editor J].

Anyway here are the steps to implement it

·         Create template, layout and content item for error page. I am creating only two fields in template here – Error Title, Error Message
·         On error page, I am displaying information of both these fields entered by content tree.
·         Generally I am creating single layout for all the contents. So I implemented the Page_Error event to capture all the error generated at layout page level.
·         Here is code

/// <summary>
/// page-level exception handler
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void Page_Error(object sender, EventArgs e)
{
    // retrieve the last exception
    Exception exception = HttpContext.Current.Server.GetLastError();

    // handle any exception
    if (exception != null)
    {
        string error = exception.ToString();
        HttpContext.Current.Server.ClearError();
        ErrorLog(error);
    }
}

/// <summary>
/// Log and redirect to error page
/// </summary>
/// <param name="error"></param>
private void ErrorLog(string error)
{
    // log and clear the exception
    Sitecore.Diagnostics.Log.Error(error, this);
    // Pass the error on to the Generic Error page   
    string errorPageURL = Sitecore.Links.LinkManager.GetItemUrl(Sitecore.Context.Database.Items.GetItem(new ID("{SSSS778C-JKHJ-SKSK-A01C-411E2028KKKK}")));
    Response.Redirect(errorPageURL);
}


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

Thursday, April 16, 2015

How to create XML Sitemap for Sitecore website programmatically

There are time when you are going to deploy your website on production and client want Sitemap file of website. Sitemap file is used to improve SEO results.

Sometimes client have some weird requirement that create XML sitemap dynamically for Sitecore website.

For this type of requirement, always keep one field "Show Sitemap" in all the page content.

Here is a code to generate sitemap dynamically. Remember you need a permission to update Sitemap.xml file on server.

public bool GenerateXml(List<Tuple<string, string, string>> lstTuples)  //generateXml
{
    bool result = false;
    string xmlFile = HttpContext.Current.Server.MapPath("/Sitemap.xml");

    XmlTextWriter writer = new XmlTextWriter(xmlFile, System.Text.Encoding.UTF8);
    writer.Formatting = Formatting.Indented;
    writer.WriteStartDocument();
    {
        writer.WriteStartElement("urlset");
        writer.WriteAttributeString("xmlns:xhtml", "http://www.w3.org/1999/xhtml");
        writer.WriteAttributeString("xmlns", "http://www.sitemaps.org/schemas/sitemap/0.9");

        string url = "http://" + System.Web.HttpContext.Current.Request.ServerVariables["HTTP_HOST"];

        foreach (var value in lstTuples)
        {
            writer.WriteStartElement("url");
            writer.WriteElementString("loc", System.Web.HttpUtility.HtmlEncode(url + value.Item2));
            writer.WriteElementString("lastmod", value.Item3);
            writer.WriteElementString("changefreq", "weekly");
            writer.WriteElementString("priority", "0.5");
            writer.WriteEndElement();
        }

        writer.WriteEndElement();
        writer.WriteEndDocument();
        writer.Flush();

        result = true;
    }

    return result;

}

Pass the Tuple collection which contains URL and last modified date of content items.
This code should create file with below data

<?xml version="1.0" encoding="utf-8"?>
<urlset xmlns:xhtml="http://www.w3.org/1999/xhtml" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <url>
    <loc>http://test/</loc>
    <lastmod>2015-04-06</lastmod>
    <changefreq>weekly</changefreq>
    <priority>0.5</priority>
  </url>
  <url>
    <loc>http://test/Main Menu/Page1</loc>
    <lastmod>2015-03-23</lastmod>
    <changefreq>weekly</changefreq>
    <priority>0.5</priority>
  </url>


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

Monday, April 13, 2015

How to do versioning of JS and CSS files in ASP.NET

Whenever user access any website - images, JS and CSS are cached by browser. But if JS and CSS are updated on server still client browser refer the old JS and CSS. That’s very bad. It’s always good practice to provide the latest copy of CSS and JS to client browser.

But how to do it in ASP.NET to make sure browser is getting the updated files.

To solve this, we can use query string with JS and CSS.

For CSS, take one literal in <Head> section of aspx page as below

<head runat="server">
<asp:Literal ID="ltStyleCss" runat="server" Text="" ></asp:Literal>
</head>

Write below code

public string CurrentVersion = "";

protected void Page_Load(object sender, EventArgs e)
{
CurrentVersion = DateTime.Today.ToString("MMddyyyy") + "_" + DateTime.Now.Hour.ToString();

ltStyleCss.Text = string.Format("<link href=\"/ css/style.css?ver={0}\" rel=\"stylesheet\" />", CurrentVersion) + System.Environment.NewLine;


Here we are declaring version for each hour of the day.

You can do it for each request by specifyin current datetime, but problem with that approach is that it affects network bandwidth. So per hour solution is better.

It’s very easy to specify it for JS by directly passing the version variable as query string  

<script src="/Presentation/scripts/jquery.js?ver=<%=CurrentVersion%>"></script>

Pretty simple for JS but you can’t achieve the same way for CSS. Let me know if you can do it for CSS as well.


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