Search
Submit & Win
Submit and win
Cash Prizes !
Winners

Win Prizes

Social Presence
Twitter Twitter LinkedIn YouTube Google

Like us on Facebook
Advertisements
Top Articles Author
Sat, 20-Dec-2014 Authors
All Time Authors
Sourav.Kayal
39750
SheoNarayan
38550
Niladri.biswas
33350

Latest members | More ...


(Statistics delayed by 5 minutes)
Ads
 Article

Improve Application Performance using HTTP Handler

Rama Sagar
Posted by under ASP.NET category on for Beginner level | Points: 250 | Views : 4400 red flag
If you found plagiarised (copied) or inappropriate content,
please let us know the original source along with your correct email id (to communicate) for further action.
An ASP.NET HTTP handler is the process that runs in response to a request that is made to an ASP.NET Web application. The most common handler is an ASP.NET page handler that processes .aspx files. When users request an .aspx file, the request is processed by the page handler.The ASP.NET page handler is only one type of handler. ASP.NET includes several other built-in handlers such as the Web service handler for .asmx files.

 Download source code for Improve Application Performance using HTTP Handler


Introduction

This article explains about how to improve application performance using HTTP Handlers

An ASP.NET HTTP handler is the process (frequently referred to as the "endpoint") that runs in response to a request made to an ASP.NET Web application. The most common handler is an ASP.NET page handler that processes .aspx files. When users request an .aspx file, the request is processed by the page through the page handler. You can create your own HTTP handlers that render custom output to the browser.


To reduce the page load time of the web pages in our application, we can compress content, cache them and then load them on demand. Each time a css or a script file is loaded, it takes some time for the browser to download the content and slows down the application until the loading of the css or scripts are over. We can use a HTTP Handler to combine the script and css files, cache them and then load the compressed content for faster page load in our application. The first time the files are requested for, they would be loaded in the cache and then served - each subsequent requests for those files would then be served from the cache only. This would reduce the load time and provide much better responsiveness as the application wouldn't have to wait for the files to be loaded from the disk onto memory and then to the browser's context. Fetching content in this way would improve the application's performance to a considerable extent. We can use a HttpHandler which when injected to the response stream would compress content, cache it and then fetch it to the web page. 

Let us start using the Handler

Using this handler is also simple. All we need is a few simple steps outlined below:

1. Include the handler in the web project

#region Namespaces
using System;
using System.Net;
using System.IO;
using System.IO.Compression;
using System.Text;
using System.Web;
#endregion

namespace PerformanceOptimizationDemo
{
    /// <summary>
    /// CompressFiles handler for compressing scripts and style sheets and storing them in the cache.
    /// </summary>
    public class CompressFiles : IHttpHandler
    {
        #region Data members

        private const bool COMPRESSCONTENT = true;
        private const string CACHE_KEY_PREFIX = "HttpCompress.";
        private readonly static TimeSpan CACHE_DURATION = TimeSpan.FromHours(10);

        #endregion

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        public void ProcessRequest(HttpContext context)
        {
            HttpRequest request = context.Request;

            // Read setName, contentType and version. All are required. They are
            // used as cache key
            string setName = request["s"] ?? string.Empty;
            string contentType = request["t"] ?? string.Empty;
            string version = request["v"] ?? string.Empty;

            // Decide if browser supports compressed response
            bool isCompressed = COMPRESSCONTENT && this.IsGZipEnabled(context.Request);

            // Response is written as UTF8 encoding. If you are using languages like
            // Arabic, you should change this to proper encoding 
            UTF8Encoding encoding = new UTF8Encoding(false);

            // If the set has already been cached, write the response directly from
            // cache. Otherwise generate the response and cache it
            if (!this.WriteBytesFromCache(context, setName, version, isCompressed, contentType))
            {
                using (MemoryStream memoryStream = new MemoryStream(5000))
                {
                    // Decide regular stream or GZipStream based on whether the response
                    // can be cached or not
                    using (Stream writer = isCompressed ?
                        (Stream)(new GZipStream(memoryStream, CompressionMode.Compress)) :
                        memoryStream)
                    {

                        // Load the files defined in <appSettings> and process each file
                        string setDefinition =
                            System.Configuration.ConfigurationManager.AppSettings[setName] ?? "";
                        string[] fileNames = setDefinition.Split(new char[] { ',' },
                            StringSplitOptions.RemoveEmptyEntries);

                        foreach (string fileName in fileNames)
                        {
                            byte[] fileBytes = this.GetFileContent(context, fileName.Trim(), encoding);
                            writer.Write(fileBytes, 0, fileBytes.Length);
                        }

                        writer.Close();
                    }

                    // Cache the combined response so that it can be directly written
                    // in subsequent calls 
                    byte[] responseBytes = memoryStream.ToArray();
                    context.Cache.Insert(GetKeyFromCache(setName, version, isCompressed),
                        responseBytes, null, System.Web.Caching.Cache.NoAbsoluteExpiration,
                        CACHE_DURATION);

                    // Generate the response
                    this.WriteBytes(responseBytes, context, isCompressed, contentType);
                }
            }
        }

        #region Private methods

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="virtualPath"></param>
        /// <param name="encoding"></param>
        /// <returns></returns>
        private byte[] GetFileContent(HttpContext context, string virtualPath, Encoding encoding)
        {
            if (virtualPath.StartsWith("http://", StringComparison.InvariantCultureIgnoreCase))
            {
                using (WebClient client = new WebClient())
                {
                    return client.DownloadData(virtualPath);
                }
            }
            else
            {
                string physicalPath = context.Server.MapPath(virtualPath);
                byte[] bytes = File.ReadAllBytes(physicalPath);
                return bytes;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="setName"></param>
        /// <param name="version"></param>
        /// <param name="isCompressed"></param>
        /// <param name="contentType"></param>
        /// <returns></returns>
        private bool WriteBytesFromCache(HttpContext context, string setName, string version,
            bool isCompressed, string contentType)
        {
            byte[] responseBytes = context.Cache[GetKeyFromCache(setName, version, isCompressed)] as byte[];

            if (null == responseBytes || 0 == responseBytes.Length) return false;

            this.WriteBytes(responseBytes, context, isCompressed, contentType);
            return true;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="bytes"></param>
        /// <param name="context"></param>
        /// <param name="isCompressed"></param>
        /// <param name="contentType"></param>
        private void WriteBytes(byte[] bytes, HttpContext context,
            bool isCompressed, string contentType)
        {
            HttpResponse response = context.Response;

            response.AppendHeader("Content-Length", bytes.Length.ToString());
            response.ContentType = contentType;

            if (isCompressed)
                response.AppendHeader("Content-Encoding", "gzip");

            context.Response.Cache.SetCacheability(HttpCacheability.Public);
            context.Response.Cache.SetExpires(DateTime.Now.Add(CACHE_DURATION));
            context.Response.Cache.SetMaxAge(CACHE_DURATION);
            context.Response.Cache.AppendCacheExtension("must-revalidate, proxy-revalidate");

            response.OutputStream.Write(bytes, 0, bytes.Length);
            response.Flush();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        private bool IsGZipEnabled(HttpRequest request)
        {
            string acceptEncoding = request.Headers["Accept-Encoding"];
            if (!string.IsNullOrEmpty(acceptEncoding) &&
                 (acceptEncoding.Contains("gzip") || acceptEncoding.Contains("deflate")))
                return true;
            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="setName"></param>
        /// <param name="version"></param>
        /// <param name="isCompressed"></param>
        /// <returns></returns>
        private string GetKeyFromCache(string setName, string version, bool isCompressed)
        {
            return CACHE_KEY_PREFIX + setName + "." + version + "." + isCompressed;
        }

        #endregion

        /// <summary>
        /// IsReusable property
        /// </summary>
        public bool IsReusable
        {
            get
            {
                return true;
            }
        }
    }
}

2. Define the files to be compressed and cached in the <appSettings> section of the web.config of the web project

<?xml version="1.0"?>
<configuration>
  
  <appSettings>
    <add key="Css_Files" value="~/Styles/Css1.css,~/Styles/Css2.css,~/Styles/jquery.ribbon.css,~/Styles/liteaccordion.css"/>
    <add key="Script_Files" value="~/Scripts/Js1.js,~/Scripts/Js2.js,~/Scripts/jquery.js"/>
  </appSettings>
  
    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>
</configuration>
3. Invoke the handler in the master page or content page as appropriate

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Demo.aspx.cs" Inherits="PerformanceOptimizationDemo.Demo" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Demo Application</title>
    <link type="text/css" 
            rel="Stylesheet" 
            href="CompressFiles.ashx?s=Css_Files&t=text/css&v=1" />
</head>
<body>
<script type="text/javascript" 
        src="CompressFiles.ashx?s=Script_Files&t=type/javascript&v=1" >
</script>

    <form id="form1" runat="server">
    <div>
    
    </div>
    </form>
</body>
</html>


Conclusion

In this article we have learned how to optimize Application Performance using HTTP Handler.Please find the attached source code

Reference

http://msdn.microsoft.com/en-us/library/bb398986(v=vs.100).ASPX

Page copy protected against web site content infringement by Copyscape
About the Author

Rama Sagar

Full Name: RamaSagar Pulidindi
Member Level: Silver
Member Status: Member
Member Since: 12/30/2012 1:51:40 AM
Country: India
ramasagar
http://www.ramasagar.com

A Software Profesional working in Microsoft .NET technologies since year 2008, and I work for Dake ACE. I am passionate about .NET technology and love to contribute to the .NET community at Dot Net Funda
Login to vote for this post.
Share this to:

Bookmark It

Comments or Responses

Posted by: Anant on: 11/22/2013 | Points: 25

is it any permission is required to use gZip on live server?

Login to post response

Comment using Facebook(Author doesn't get notification)