利用ResultFilter实现asp.net mvc3 页面静态化
为了提高网站性能、和网站的负载能力,页面静态化是一种有效的方式,这里对于asp.net mvc3 构架下的网站,提供一种个人认为比较好的静态话方式。
实现原理是通过mvc提供的过滤器扩展点实现页面内容的文本保存,直接上代码:
View Code
public class StaticFileWriteFilterAttribute : FilterAttribute, IResultFilter
{
public void OnResultExecuted(ResultExecutedContext filterContext)
{
}
public void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Filter = new StaticFileWriteResponseFilterWrapper(filterContext.HttpContext.Response.Filter, filterContext);
}
class StaticFileWriteResponseFilterWrapper : System.IO.Stream
{
private System.IO.Stream inner;
private ControllerContext context;
public StaticFileWriteResponseFilterWrapper(System.IO.Stream s,ControllerContext context)
{
this.inner = s;
this.context = context;
}
public override bool CanRead
{
get { return inner.CanRead; }
}
public override bool CanSeek
{
get { return inner.CanSeek; }
}
public override bool CanWrite
{
get { return inner.CanWrite; }
}
public override void Flush()
{
inner.Flush();
}
public override long Length
{
get { return inner.Length; }
}
public override long Position
{
get
{
return inner.Position;
}
set
{
inner.Position = value;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
return inner.Read(buffer, offset, count);
}
public override long Seek(long offset, System.IO.SeekOrigin origin)
{
return inner.Seek(offset, origin);
}
public override void SetLength(long value)
{
inner.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
inner.Write(buffer, offset, count);
try
{
string p = context.HttpContext.Server.MapPath(HttpContext.Current.Request.Path);
if (Path.HasExtension(p))
{
string dir = Path.GetDirectoryName(p);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
if (File.Exists(p))
{
File.Delete(p);
}
File.AppendAllText(p, System.Text.Encoding.UTF8.GetString(buffer));
}
}
catch
{
}
}
}
}
{
public void OnResultExecuted(ResultExecutedContext filterContext)
{
}
public void OnResultExecuting(ResultExecutingContext filterContext)
{
filterContext.HttpContext.Response.Filter = new StaticFileWriteResponseFilterWrapper(filterContext.HttpContext.Response.Filter, filterContext);
}
class StaticFileWriteResponseFilterWrapper : System.IO.Stream
{
private System.IO.Stream inner;
private ControllerContext context;
public StaticFileWriteResponseFilterWrapper(System.IO.Stream s,ControllerContext context)
{
this.inner = s;
this.context = context;
}
public override bool CanRead
{
get { return inner.CanRead; }
}
public override bool CanSeek
{
get { return inner.CanSeek; }
}
public override bool CanWrite
{
get { return inner.CanWrite; }
}
public override void Flush()
{
inner.Flush();
}
public override long Length
{
get { return inner.Length; }
}
public override long Position
{
get
{
return inner.Position;
}
set
{
inner.Position = value;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
return inner.Read(buffer, offset, count);
}
public override long Seek(long offset, System.IO.SeekOrigin origin)
{
return inner.Seek(offset, origin);
}
public override void SetLength(long value)
{
inner.SetLength(value);
}
public override void Write(byte[] buffer, int offset, int count)
{
inner.Write(buffer, offset, count);
try
{
string p = context.HttpContext.Server.MapPath(HttpContext.Current.Request.Path);
if (Path.HasExtension(p))
{
string dir = Path.GetDirectoryName(p);
if (!Directory.Exists(dir))
{
Directory.CreateDirectory(dir);
}
if (File.Exists(p))
{
File.Delete(p);
}
File.AppendAllText(p, System.Text.Encoding.UTF8.GetString(buffer));
}
}
catch
{
}
}
}
}
我们的类StaticFileWriteFilterAttribute实现了IResultFilter,这个接口有两个方法,OnResultExecuted和OnResultExecuting,其中OnResultExecuting是在controller中的action代码执行完毕后,但viewresult执行之前(即页面内容生成之前)执行;OnResultExecuted方法是在viewresult执行之后(即页面内容生成之后)执行。
我们在页面生成之前将StaticFileWriteResponseFilterWrapper类注册给Response对象的Filter属性,这里使用包装类可以在没有副作用的情况下注入页面内容静态化的代码,对于处理业务逻辑的action是透明的。