MVC 頁面靜態化
最近工作需要,實現頁面靜態化,以前在ASP時代,都是FSO自己手動生成的。
新時代,MVC了,當然也要新技術,網上一搜,找到一種解決方案,是基於MVC3的,實現原理是通過mvc提供的過濾器擴展點實現頁面內容的文本保存。
基本原理為:
1.為需要靜態化的Action上加一個自定義的實現了IResultFilter的Attribute(具體見下文)
2.添加一條路由規則,實現訪問靜態頁面,把它放在原有路由的前面
//http://product/123.html routes.MapRoute( "HTMLDefault", // Route name "product/{id}.html", // URL with parameters new { controller = "Home", action = "ProductDetails", id = 0 } // Parameter defaults );
(准備應用在項目中做如下規划:管事員后台修改/刪除產品,同時修改/刪除其對應頁面,添加無須創建頁面,因為用戶訪問時會自動創建)
另外,原文下有同學反應
不會代碼的人 因為每次只能寫入一定數量的文字,如果過大就會再次寫入,再次寫入的話,樓主寫了下面這判斷: if (File.Exists(p)) { File.Delete(p); } 存在就給刪除了,所以只寫入最后的一些文字
目前網頁沒太大,所以具體情況不清楚,用到再說了哈。
實現效果如下:
但為了達到以上效果,雖然照般教程,但還是無法實現,原因就是我用的VS2012,MVC4,web.config(網站根目錄下)有所改變,經過對比
發現:
只要在system.webServer結點下添加一條
<modules runAllManagedModulesForAllRequests="true"/>
即可,否則,因為你路由設置了靜態頁面HTML,它會提示你找不到文件,404錯誤,切記切記。
以下為轉載的文章,方便學習:
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 (Exception ex) { } } } }
我們的類StaticFileWriteFilterAttribute實現了IResultFilter,這個接口有兩個方法,OnResultExecuted和OnResultExecuting,其中OnResultExecuting是在controller中的action代碼執行完畢后,但viewresult執行之前(即頁面內容生成之前)執行;OnResultExecuted方法是在viewresult執行之后(即頁面內容生成之后)執行。
我們在頁面生成之前將StaticFileWriteResponseFilterWrapper類注冊給Response對象的Filter屬性,這里使用包裝類可以在沒有副作用的情況下注入頁面內容靜態化的代碼,對於處理業務邏輯的action是透明的。
使用方式:
全局注冊:GlobalFilters.Filters.Add(new StaticFileWriteFilterAttribute ());
單獨controller注冊
public class MyController:Controller
{
[StaticFileWriteFilter]
public ActionResult MyAction()
{
}
}
在Global.asax中的RegisterRoutes 添加路由
routes.MapRoute( "HTMLDefault", // Route name "Subject/Index/{ArticleId}_{PageIndex}.html", // URL with parameters new { controller = "Subject", action = "Index", ArticleId = 0, PageIndex=0 } // Parameter defaults );
例如用戶訪問http://localhost:3509/Home/About.html如果不存在此靜態文件 則訪問action,action訪問后則自動生成了此html文件,下次用戶訪問這個地址,就是訪問靜態文件了,不會進入action代碼了。
原文地址:
http://www.cnblogs.com/TeyGao/archive/2012/06/01/2530743.html
http://www.cnblogs.com/gowhy/archive/2013/01/01/2841472.html