ASP.NET MVC View呈现[实例篇]

  在《ASP.NET MVC View呈现[设计篇]》篇中通过对View引擎的总体介绍讲述了从ViewResult的创建到View呈现的原理,为了让读者对View引擎及其View呈现机制具有一个深刻的认识,我们自定义一个简单的用于呈现静态HTML的StaticFileViewEngine。 在一个通过Visual Studio的ASP.NET MVC项目模板创建的空Web应用中,我们定义了如下一个针对于静态HTML内容呈现的自定义StaticFileView。 StaticFileView实现了IView接口,在实现的Render方法中读取制定文件的内容写入作为参数的TextWriter。

   1: public class StaticFileView:IView

   2: {

   3:     public string FileName { get; private set; }

   4:     public StaticFileView(string fileName)

   5:     {

   6:         this.FileName = fileName;

   7:     }

   8:     public void Render(ViewContext viewContext, TextWriter writer)

   9:     {

  10:         byte[] buffer;

  11:         using (FileStream fs = new FileStream(this.FileName, FileMode.Open))

  12:         { 

  13:             buffer = new byte[fs.Length];

  14:             fs.Read(buffer, 0, buffer.Length);

  15:         }

  16:         writer.Write(Encoding.UTF8.GetString(buffer));

  17:     }

  18: }

  由于StaticFileView中定义的内容完全是静态的,所以缓存显得很有必要。我们只需要基于Controller和View名称对View实施缓存,为此我们定义了如下一个作为Key的数据类型ViewEngineResultCacheKey。

   1: internal class ViewEngineResultCacheKey

   2: {

   3:     public string ControllerName { get; private set; }

   4:     public string ViewName { get; private set; }

   5:  

   6:     public ViewEngineResultCacheKey(string controllerName, string viewName)

   7:     {

   8:         this.ControllerName = controllerName ?? string.Empty;

   9:         this.ViewName = viewName ?? string.Empty;

  10:     }

  11:     public override int GetHashCode()

  12:     {

  13:         return this.ControllerName.ToLower().GetHashCode() ^ this.ViewName.ToLower().GetHashCode();

  14:     }

  15:  

  16:     public override bool Equals(object obj)

  17:     {

  18:         ViewEngineResultCacheKey key = obj as ViewEngineResultCacheKey;

  19:         if (null == key)

  20:         {

  21:             return false;

  22:         }

  23:         return key.GetHashCode() == this.GetHashCode();

  24:     }

  25: }

  具有如下定义的StaticFileViewEngine代表StaticFileView对应的ViewEngine。我们通过一个字典类型的字 段viewEngineResults作为对ViewEngineResult的缓存,而View的获取操作最终实现在InternalFindView 方法中。通过StaticFileView表示的View定义在一个以View名称作为文件名的文本文件中,该文件的扩展名为.shtml(Static HTML)。

   1: public class StaticFileViewEngine : IViewEngine

   2: {

   3:     private Dictionary<ViewEngineResultCacheKey, ViewEngineResult> viewEngineResults = new Dictionary<ViewEngineResultCacheKey, ViewEngineResult>();

   4:     private object syncHelper = new object();

   5:     public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)

   6:     {

   7:         return this.FindView(controllerContext, partialViewName, null, useCache);

   8:     }

   9:  

  10:     public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)

  11:     {

  12:         string controllerName = controllerContext.RouteData.GetRequiredString("controller");

  13:         ViewEngineResultCacheKey key = new ViewEngineResultCacheKey(controllerName, viewName);

  14:         ViewEngineResult result;

  15:         if (!useCache)

  16:         { 

  17:             result = InternalFindView(controllerContext, viewName, controllerName);

  18:             viewEngineResults[key] = result;

  19:             return result;

  20:         }

  21:         if(viewEngineResults.TryGetValue(key, out result))

  22:         {

  23:             return result;

  24:         }

  25:         lock (syncHelper)

  26:         {

  27:             if (viewEngineResults.TryGetValue(key, out result))

  28:             {

  29:                 return result;

  30:             }

  31:  

  32:             result = InternalFindView(controllerContext, viewName, controllerName);

  33:             viewEngineResults[key] = result;

  34:             return result;

  35:         }             

  36:     }

  37:  

  38:     private ViewEngineResult InternalFindView(ControllerContext controllerContext, string viewName, string controllerName)

  39:     {

  40:         string[] searchLocations = new string[]

  41:         {

  42:             string.Format( "~/views/{0}/{1}.shtml", controllerName, viewName),

  43:             string.Format( "~/views/Shared/{0}.shtml", viewName)

  44:         };

  45:  

  46:         string fileName = controllerContext.HttpContext.Request.MapPath(searchLocations[0]);

  47:         if (File.Exists(fileName))

  48:         {

  49:             return new ViewEngineResult(new StaticFileView(fileName), this);

  50:         }

  51:         fileName = string.Format(@"\views\Shared\{0}.shtml", viewName);

  52:         if (File.Exists(fileName))

  53:         {

  54:             return new ViewEngineResult(new StaticFileView(fileName), this);

  55:         }

  56:         return new ViewEngineResult(searchLocations);

  57:     }

  58:  

  59:     public void ReleaseView(ControllerContext controllerContext, IView view)

  60:     { }

  61: }

  在InternalFindView中,我们先在“~/Views/{ControllerName}/”目录下寻找View文件,如果不存在则在“~/Views/Shared/”寻 找。如果对应View文件被找到,则以此创建一个StaticFileView对象,并最终返回封装该View对象的ViewEngineResult。 如果目标View文件找不到,则根据基于这两个目录的搜寻地址列表创建并返回对应的ViewEngineResult。 现在我们在Global.asax通过如下的代码对自定义的StaticFileViewEngine进行注册,我们将创建的 StaticFileViewEngine作为第一个使用的ViewEngine。

   1: public class MvcApplication : System.Web.HttpApplication

   2: {

   3:     protected void Application_Start()

   4:     {

   5:         //其他操作

   6:         ViewEngines.Engines.Insert(0, new StaticFileViewEngine());

   7:     }

   8: }

  然后我们定义了如下一个简单的HomeController,Action方法ShowNonExistentView中通过调用View方法呈现 一个不存在的View(NonExistentView),而ShowStaticFileView方法则将对应的StaticFileView呈现出 来。

   1: public class HomeController : Controller

   2: {

   3:     public ActionResult ShowNonExistentView()

   4:     {

   5:         return View("NonExistentView");

   6:     }

   7:  

   8:     public ActionResult ShowStaticFileView()

   9:     {

  10:         return View();

  11:     }

  12: }

  我们为Action方法ShowStaticFileView创建一个StaticFileView类型的View文件 ShowStaticFileView.shtml(该View文件保存在“~/Views/Home”目录下,扩展名不是.cshtml,而是 shtml),其内容就是如下一段完整的HTML。

   1: <!DOCTYPE html>

   2: <html>

   3:     <head>

   4:         <title>Static File View</title>

   5:     </head>

   6:     <body>

   7:         这是一个自定义的StaticFileView!

   8:     </body>

   9: </html>

  现在运行我们的程序,在浏览器中输入相应的地址访问Action方法ShowNonExistentView,会得到如下图所示的输出结果。图中列 出的View搜寻位置列表中的前两项正是我们自定义的StaticFileViewEngine寻找对应.shtml文件的两个地址。

ASP.NET MVC View呈现[实例篇]

  如果我们改变浏览器的地址来访问另一个Action方法ShowStaticFileView,会呈现出如下图所示的输出结果,不难看出呈现出来的正是定义在ShowStaticFileView.shtml中的HTML。

ASP.NET MVC View呈现[实例篇]

作者:Artech
出处:http://artech.cnblogs.com/

评论(0)网络
阅读(42)喜欢(0)不喜欢(0)asp.net-mvc