Search Wiki:
For description go to http://www.mikhaildikov.com/2008/10/caching-of-dynamic-resources.html

public class MyWebResourceHandler : System.Web.IHttpHandler
{
 
	#region IHttpHandler Members
 
	public bool IsReusable
	{
			get { return true; }
	}
 
	[Description("Serves the localized resource.")]
	public void ProcessRequest(HttpContext context)
	{
		// Setting the last modified date to the creation data of the assembly
		Assembly thisAssembly = Assembly.GetExecutingAssembly();
		string thisPath = thisAssembly.CodeBase.Replace(@"file:///", "");
		string assemblyName = resourceName.Split(':')[0] + ".dll";
		string assemblyPath = thisPath.Replace(thisAssembly.ManifestModule.ScopeName, assemblyName);
		DateTime creationDate;
		using (Identity impersonate = Identity.ImpersonateAdmin())
		{
				FileInfo assemblyInfo = new FileInfo(assemblyPath);
				creationDate = assemblyInfo.CreationTime;
		}
		
		string ETag = GetFileETag(assemblyPath, creationDate);			   
 
		if (IsFileModified(assemblyPath, creationDate, ETag, context.Request))
		{
			context.Response.ContentType = <specify content type>;
						   
			// Do resource processing here
 
			context.Response.Write(<specify resource content>);
		}
		else
		{
			// File hasn't changed, so return HTTP 304 without retrieving the data 
			context.Response.StatusCode = 304;
			context.Response.StatusDescription = "Not Modified";
 
			// Explicitly set the Content-Length header so the client doesn't wait for
			//  content but keeps the connection open for other requests 
			context.Response.AddHeader("Content-Length", "0");		   
		}
 
		// set cache info
		context.Response.Cache.SetCacheability(HttpCacheability.Private);
		context.Response.Cache.VaryByHeaders["If-Modified-Since"] = true;
		context.Response.Cache.VaryByHeaders["If-None-Match"] = true;		  
		context.Response.Cache.SetLastModified(creationDate);		
		context.Response.Cache.SetETag(ETag);
		context.Response.End();
	}
	#endregion
 
	/// <summary>
	/// Checks if the resource assembly has been modified based on creation date.
	/// </summary>
	/// <remarks>
	/// </remarks>
	/// <seealso cref="GetFileETag"/>
	private bool IsFileModified(string fileName, DateTime modifyDate, string eTag, HttpRequest request)
	{
		// Assume file has been modified unless we can determine otherwise 
		bool FileDateModified = true;
		DateTime ModifiedSince;
		TimeSpan ModifyDiff;
		bool ETagChanged;
 
		// Check If-Modified-Since request header, if it exists 
		string ifModifiedSince = request.Headers["If-Modified-Since"];
		if (!string.IsNullOrEmpty(ifModifiedSince) && ifModifiedSince.Length > 0 && DateTime.TryParse(ifModifiedSince, out ModifiedSince))
		{
			FileDateModified = false;
			if (modifyDate > ModifiedSince)
			{
				ModifyDiff = modifyDate - ModifiedSince;
				// Ignore time difference of up to one seconds to compensate for date encoding
				FileDateModified = ModifyDiff > TimeSpan.FromSeconds(1);
			}
		}
		// Check the If-None-Match header, if it exists. This header is used by FireFox to validate entities based on the ETag response header 
		ETagChanged = false;
		string ifNoneMatch = request.Headers["If-None-Match"];
		if (!string.IsNullOrEmpty(ifNoneMatch) && ifNoneMatch.Length > 0)
		{
			ETagChanged = ifNoneMatch != eTag;
		}
		return ETagChanged || FileDateModified;
	}
 
	/// <summary>
	/// Generates a caching ETag based on file name and creation date.
	/// </summary>
	/// <remarks>
	/// </remarks>
	/// <seealso cref="GetFileETag"/>
	private string GetFileETag(string fileName, DateTime modifyDate)
	{
		string fileString;
		Encoder stringEncoder;
		int byteCount;
		Byte[] stringBytes;
 
		// Use file name and modify date as the unique identifier 
		fileString = fileName + modifyDate.ToString();
 
		// Get string bytes 
		stringEncoder = Encoding.UTF8.GetEncoder();
		byteCount = stringEncoder.GetByteCount(fileString.ToCharArray(), 0, fileString.Length, true);
		stringBytes = new Byte[byteCount];
 
		stringEncoder.GetBytes(fileString.ToCharArray(), 0, fileString.Length, stringBytes, 0, true);
 
		//{ Hash string using MD5 and return the hex-encoded hash }
		MD5 Enc = MD5CryptoServiceProvider.Create();
		return "\"" + BitConverter.ToString(Enc.ComputeHash(stringBytes)).Replace("-", string.Empty) + "\"";
 
	}
}
 
Last edited Nov 25 2008 at 8:52 PM  by mdikov, version 3
Updating...
Page view tracker