[ASP.NET MVC 专题] ViewEngine的发展以及应用

[ASP.NET MVC 专题]

    [ASP.NET MVC 专题] 如何为Route构造相关的自定义Configuration

    [ASP.NET MVC 专题] ViewEngine的发展以及应用  

 

                                                    ViewEngine的发展以及应用

()MVC1版本的ViewEngine

 

 

从上图,我们可以知道:(1)当客户端发送请求时,DefaultControllerFactory根据RequestContext对象和ControllerName来生成我们的Controller。Controller的ViewDataDictionary将保存相关的数据,并且通过ViewEngine传递给View。

public virtual IController CreateController(RequestContext requestContext, string controllerName)
{
    Type controllerType = 
this.GetControllerType(requestContext, controllerName); //type = this.GetControllerTypeWithinNamespaces(requestContext.RouteData.Route, controllerName, namespaces);
    return this.GetControllerInstance(requestContext, controllerType);
}

protected internal virtual IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
    
return  (IController) Activator.CreateInstance(controllerType);//反射
}

 

 

2)在我们以前的MVC版本中,Controller拥有ViewEngine的属性。我们先看下下述的代码:ViewEngine依据ViewContextViewLocator怎么处理View以及响应客户端??

public void RenderView(ViewContext viewContext)
        {
            
string viewLocation = ViewLocator.GetViewLocation(viewContext, viewContext.ViewName);//
根据ViewContext以及相关内容获取view的相对文件路径
            string viewPath = viewContext.HttpContext.Request.MapPath(viewLocation););//获取view的绝对文件路径
            string viewTemplate = File.ReadAllText(viewPath);//读取文件内容
            IRenderer renderer = new PrintRenderer();
            viewTemplate = renderer.Render(viewTemplate, viewContext);
//正则表达式处理相应内容,难点!
            viewContext.HttpContext.Response.Write(viewTemplate);//发送响应到客户端
        }

 

从上面的代码中,我们能够清晰的看到,总体框架就是这么赤裸裸的“请求--->响应”。虽然代码是过去版本的,但是依旧能够使我们比较容易的理解整个过程的细节。

关于以前版本的自定义ViewEngine请参考http://blog.maartenballiauw.be/post/2008/05/Creating-a-custom-ViewEngine-for-the-ASPNET-MVC-framework.aspx

 

(二)随着MVC版本的改进,我们的ViewEngine一直在变,从未被超越。ViewLocator不再使用了,将属性整合到ViewEngine中了。先看下我们的继承链上的LocationFormats,如下:

public   abstract   class  VirtualPathProviderViewEngine : IViewEngine
    {
         
public   string [] AreaMasterLocationFormats {  get set ; }
         
public   string [] AreaPartialViewLocationFormats {  get set ; }
         
public   string [] AreaViewLocationFormats {  get set ; }
         
public   string [] MasterLocationFormats {  get set ; }
         
public   string [] PartialViewLocationFormats {  get set ; }
         
public   string [] ViewLocationFormats {  get set ; }
    } 

 

 

上面的6个属性就涵盖了我们的代码文件的相对路径形式。如果要改变我们的代码文件路径,我们需要设置一下我们自己的LocationFormats。我们仅仅需要做的就是将父类的属性重新设置成相关的路径形式既可,如下示例:

 

 1  public   class  HomeViewEngine : WebFormViewEngine
 2      {
 3           public  HomeViewEngine():  this ( " Default " )
 4          {
 5          }
 6           public  HomeViewEngine( string  directory){
 7              MasterLocationFormats  =   new []{ 
 8                   string .Format( " ~/{0}/{{1}}/{{0}}.master " , directory),
 9                   string .Format( " ~/{0}/shared/{{0}}.master " , directory)
10              };
11              ViewLocationFormats  =   new []{
12                   string .Format( " ~/{0}/{{1}}/{{0}}.aspx " , directory),
13                   string .Format( " ~/{0}/{{1}}/{{0}}.ascx " , directory),
14                   string .Format( " ~/{0}/shared/{{0}}.aspx " , directory),
15                   string .Format( " ~/{0}/shared/{{0}}.ascx " , directory)
16              };
17              PartialViewLocationFormats  =  ViewLocationFormats;
18          }
19           public   override  ViewEngineResult FindView(ControllerContext controllerContext,  string  viewName,  string  masterName,  bool  useCache){
20               return   base .FindView(controllerContext, viewName, masterName, useCache);
21          }
22           public   override  ViewEngineResult FindPartialView(ControllerContext controllerContext,  string  partialViewName,  bool  useCache){
23               return   base .FindPartialView(controllerContext, partialViewName, useCache);
24          }
25      }

 

将属性重新赋值后,相对路径就改变了,系统会通过GetLocation()方法获取每次请求匹配的相对视图路径地址。我们可以通过ViewEngineCollection(IList<T>)来添加自己的ViewEngine。如下所示,我们通过双检锁的技巧(盗版的)来添加新的ViewEngine。其他的留给系统去考虑吧,XX,封装的太厉害了,哥也有时候摸不清方向!

 

public   class  BaseHomeController :Controller 
    {
        
public   static   object  lockObj  =   new   object ();
        
private  HomeViewEngine viewEngine  =   null ;  
        
public  BaseHomeController(){
            
if  (viewEngine  ==   null ){
                
lock  (lockObj){
                    
if  (viewEngine  ==   null ){
                        viewEngine 
=   new  HomeViewEngine(); // 设置你的路径前缀目录名称,可为空
                        ViewEngines.Engines.Add(viewEngine);
                    }
                }
            }
        }
    }

 

将你的相关的代码文件放在你想放置的地方,对于public HomeViewEngine(string directory){}构造函数,我们实例化 HomeViewEngine时传递相关的参数既可。系统会根据相关路径查找文件。

 

(三)RazorViewEngine的相对文件路径如下:

public  RazorViewEngine()
{
    
base .AreaViewLocationFormats  =   new   string [] {  " ~/Areas/{2}/Views/{1}/{0}.cshtml " " ~/Areas/{2}/Views/{1}/{0}.vbhtml " " ~/Areas/{2}/Views/Shared/{0}.cshtml " " ~/Areas/{2}/Views/Shared/{0}.vbhtml "  };
    
base .AreaMasterLocationFormats  =   new   string [] {  " ~/Areas/{2}/Views/{1}/{0}.cshtml " " ~/Areas/{2}/Views/{1}/{0}.vbhtml " " ~/Areas/{2}/Views/Shared/{0}.cshtml " " ~/Areas/{2}/Views/Shared/{0}.vbhtml "  };
    
base .AreaPartialViewLocationFormats  =   new   string [] {  " ~/Areas/{2}/Views/{1}/{0}.cshtml " " ~/Areas/{2}/Views/{1}/{0}.vbhtml " " ~/Areas/{2}/Views/Shared/{0}.cshtml " " ~/Areas/{2}/Views/Shared/{0}.vbhtml "  };
    
base .ViewLocationFormats  =   new   string [] {  " ~/Views/{1}/{0}.cshtml " " ~/Views/{1}/{0}.vbhtml " " ~/Views/Shared/{0}.cshtml " " ~/Views/Shared/{0}.vbhtml "  };
    
base .MasterLocationFormats  =   new   string [] {  " ~/Views/{1}/{0}.cshtml " " ~/Views/{1}/{0}.vbhtml " " ~/Views/Shared/{0}.cshtml " " ~/Views/Shared/{0}.vbhtml "  };
    
base .PartialViewLocationFormats  =   new   string [] {  " ~/Views/{1}/{0}.cshtml " " ~/Views/{1}/{0}.vbhtml " " ~/Views/Shared/{0}.cshtml " " ~/Views/Shared/{0}.vbhtml "  };
    
this .ViewStartFileExtensions  =   new   string [] {  " cshtml " " vbhtml "  };
}

  

我们同样可以通过继承来覆盖原有的LocationFormats,这样,我们的视图文件路径也就可以随心所欲的放置在自己的目录下了。

更多Razor应用的请参考http://weblogs.asp.net/rashid/archive/2010/07/10/use-razor-as-asp-net-mvc-viewengine.aspx

 

总结

本文稍微的总结了ViewEngine的发展以及如何在项目中应用。随着MVC版本的改进,封装越来越多,很多细节被掩盖了。在Razor中,系统根据ViewEngine的相关路径属性获取的文件内容,系统如何处理@指令的?

Regex templatePattern = new Regex(@"@???", RegexOptions.Multiline);//@??

MatchEvaluator replaceCallback = new MatchEvaluator(m => HandleRegexData());
templatePattern.Replace(viewTemplate, replaceCallback);这个需进一步学习才行。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值