ASP.NET MVC的View是如何呈现出来的[实例篇]

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

   1:publicclass StaticFileView:IView
   2: {
   3:publicstring FileName { get; private set; }
   4:public StaticFileView(string fileName)
   5:     {
   6:this.FileName = fileName;
   7:     }
   8:publicvoid Render(ViewContext viewContext, TextWriter writer)
   9:     {
  10:byte[] buffer;
  11:using (FileStream fs = new FileStream(this.FileName, FileMode.Open))
  12:         { 
  13:             buffer = newbyte[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:internalclass ViewEngineResultCacheKey
   2: {
   3:publicstring ControllerName { get; private set; }
   4:publicstring 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:publicoverrideint GetHashCode()
  12:     {
  13:returnthis.ControllerName.ToLower().GetHashCode() ^ this.ViewName.ToLower().GetHashCode();
  14:     }
  15:
  16:publicoverridebool Equals(object obj)
  17:     {
  18:         ViewEngineResultCacheKey key = obj as ViewEngineResultCacheKey;
  19:if (null == key)
  20:         {
  21:returnfalse;
  22:         }
  23:return key.GetHashCode() == this.GetHashCode();
  24:     }
  25: }

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

   1:publicclass StaticFileViewEngine : IViewEngine
   2: {
   3:private Dictionary<ViewEngineResultCacheKey, ViewEngineResult> viewEngineResults
 = new Dictionary<ViewEngineResultCacheKey, ViewEngineResult>();
   4:privateobject syncHelper = newobject();
   5:public ViewEngineResult FindPartialView(ControllerContext controllerContext,
string partialViewName, bool useCache)
   6:     {
   7:returnthis.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 = newstring[]
  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:returnnew ViewEngineResult(new StaticFileView(fileName), this);
  50:         }
  51:         fileName = string.Format(@"viewsShared{0}.shtml", viewName);
  52:if (File.Exists(fileName))
  53:         {
  54:returnnew ViewEngineResult(new StaticFileView(fileName), this);
  55:         }
  56:returnnew ViewEngineResult(searchLocations);
  57:     }
  58:
  59:publicvoid ReleaseView(ControllerContext controllerContext, IView view)
  60:     { }
  61: }

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

Grow your business fast with

Suku