一定期間更新がないため広告を表示しています
In ASP .NET 2.0, I saw the new feature: Precompile.
That's one of the great features, and I need it to my current ASP .NET sites
(v1.0 and v1.1).
So I searched for it on the web, and find nothing to accomplish the same task in
v1.0 or v1.1.
That's why I made some experiments and use my own way. The idea is easy, make a
request to all aspx pages.
Here is the code I made on last March 2004.
using System;
using System.Net;
using System.Web;
using System.Web.UI;
using System.Collections.Specialized;
using System.Text;
using System.IO;
using System.Threading;
namespace Jn.Util
{
/// <summary>
/// Class for precompile the whole website
/// </summary>
public class Precompile : IHttpHandler
{
private StringCollection _dict = new StringCollection();
private HttpRequest _request = null;
private class Worker
{
private string _url = null;
public Worker(string url)
{
_url = url;
}
public void DoTask()
{
new Thread(new ThreadStart(this.Run)).Start();
}
protected void Run()
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(_url);
StreamReader reader = new StreamReader(request.GetResponse().GetResponseStream());
reader.ReadToEnd();
}
}
/// <summary>
/// Private constructor
/// </summary>
private Precompile()
{
}
private string AppVirtualDirectory
{
get
{
string port = (_request.Url.Port == 80) ? "" : ":" + _request.Url.Port;
StringBuilder temp = new StringBuilder("http://");
temp.Append(_request.Url.Host);
temp.Append(port);
temp.Append(_request.ApplicationPath);
if(!_request.ApplicationPath.EndsWith("/"))
temp.Append("/");
return temp.ToString();
}
}
/// <summary>
/// Process the request, compile the whole website
/// </summary>
/// <param name="context">Http context used to process the request</param>
public void ProcessRequest(HttpContext context)
{
_request = context.Request;
string physicalAppPath = context.Request.PhysicalApplicationPath;
this.ReadFilesAndDirectories(physicalAppPath);
for(int i=0; i<_dict.Count; i++)
{
context.Response.Write(_dict[i] + "<br>");
new Worker(_dict[i]).DoTask();
}
}
/// <summary>
/// Read files in its sub directories recursively
/// </summary>
/// <param name="physicalAppPath">Physical application path</param>
private void ReadFilesAndDirectories(string physicalAppPath)
{
DirectoryInfo directoryInfo = new DirectoryInfo(physicalAppPath);
FileInfo[] files = directoryInfo.GetFiles("*.aspx");
for(int i=0; i<files.Length; i++)
{
_dict.Add(this.AppVirtualDirectory +
files[i].FullName.Replace(_request.PhysicalApplicationPath,
"").Replace('¥¥','/'));
}
DirectoryInfo[] dirInfo = directoryInfo.GetDirectories();
for(int i=0; i<dirInfo.Length; i++)
{
if(dirInfo[i].Attributes == FileAttributes.Directory)
{
this.ReadFilesAndDirectories(dirInfo[i].FullName);
}
}
}
/// <summary>
/// IHttpHandler implementation
/// </summary>
public bool IsReusable
{
get
{
return false;
}
}
}
}
Now, compile it, I named it Jn.Util.dll.
Then add the following handler to web.config file:
<system.web>
...
<httpHandlers>
<add verb="*" path="precompile.axd" type="Jn.Util.Precompile, Jn.Util" />
</httpHandlers>
...
</system.web>
That's all.
Simply point your browser to
http://yoursite/precompile.axd, and wait until your CPU usage down to its
normal state. You may add some improvement, make a progress status page to tell
when it is done.
I left it for you to have some exercise.
Hint: make use of multithreading.
This precompile technic also demonstrate how easy it is to make an ISAPI extension using ASP .NET.
if(dirInfo[i].Attributes == FileAttributes.Directory)
should be changed to:
if((dirInfo[i].Attributes & FileAttributes.Directory) > 0)
Remember that the value of the property Attributes is a combination of the archive, compressed, directory, hidden, offline, read-only, system, and temporary file attribute flags.
If the directory has more than one attribute (besides being a directory) using the == operator won't work.