ASP.NET MVC-自分のViewEngineをカスタマイズ

9734 ワード

ASP.NET MVCがこんなに長く出てきたのに、なぜすべてのViewがViewディレクトリの下に置かれているのかと疑問に思っている.Sharedフォルダの下のページを共有できるのはなぜですか?どうしてPageは*.cshtmlは、*.aspx? 
実は上のいくつかの問題をまとめると、ビューエンジンの効果です.
従来のASP.NETでは、まだViewEngineの概念がないかもしれません.Web Fromでは、実装PageがIHttpHanlderのインタフェースを実現するため、Pageは応答の処理クラスであり、ビューのレンダリングクラスでもある.ASP.NET MVCでは,ビューの概念が抽象化され,エンジンを試みる概念もインタフェースとして抽象化される.
まず、IViewEngineインタフェースの定義を見てみましょう.
[csharp] view plain copy print ?
namespace System.Web.Mvc  
  • {  

  •     public interface IViewEngine  
  •     {  

  •         ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache);  
  •         ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);  

  •         void ReleaseView(ControllerContext controllerContext, IView view);  
  •     }  

  • }  
    namespace System.Web.Mvc
    {
        public interface IViewEngine
        {
            ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache);
            ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache);
            void ReleaseView(ControllerContext controllerContext, IView view);
        }
    }

    合計3つの関数をまとめると、Find&Releaseという2つの機能があります.
    デフォルトでは、ASP.NET MVCには、WebFormViewEngineとRazorViewEngineの2つのビューエンジンがあります.
    [csharp] view plain copy print ?
    namespace System.Web.Mvc  
  • {  

  •     public static class ViewEngines  
  •     {  

  •         private static readonly ViewEngineCollection _engines = new ViewEngineCollection  
  •         {  

  •             new WebFormViewEngine(),  
  •             new RazorViewEngine(),  

  •         };  
  •   

  •         public static ViewEngineCollection Engines  
  •         {  

  •             get { return _engines; }  
  •         }  

  •     }  
  • }  
  • namespace System.Web.Mvc
    {
        public static class ViewEngines
        {
            private static readonly ViewEngineCollection _engines = new ViewEngineCollection
            {
                new WebFormViewEngine(),
                new RazorViewEngine(),
            };
    
            public static ViewEngineCollection Engines
            {
                get { return _engines; }
            }
        }
    }

    だからASP.NET MVC既支持*.aspx、また*.cshtmlの理由です(個人的にはRazorViewを使うことが決まっているなら、WebFormViewを削除したほうが性能に役立つかもしれないと思います).
    では、なぜすべてのビューがViewsディレクトリの下に置かれているのでしょうか.これはRazorViewnginesの賜物です.
    次はRazorViewEngineのコンストラクション関数です.
    [csharp] view plain copy print ?
    public RazorViewEngine(IViewPageActivator viewPageActivator)  
  •     : base(viewPageActivator)  

  • {  
  •     AreaViewLocationFormats = new[]  

  •     {  
  •         "~/Areas/{2}/Views/{1}/{0}.cshtml",  

  •         "~/Areas/{2}/Views/{1}/{0}.vbhtml",  
  •         "~/Areas/{2}/Views/Shared/{0}.cshtml",  

  •         "~/Areas/{2}/Views/Shared/{0}.vbhtml"  
  •     };  

  •     AreaMasterLocationFormats = new[]  
  •     {  

  •         "~/Areas/{2}/Views/{1}/{0}.cshtml",  
  •         "~/Areas/{2}/Views/{1}/{0}.vbhtml",  

  •         "~/Areas/{2}/Views/Shared/{0}.cshtml",  
  •         "~/Areas/{2}/Views/Shared/{0}.vbhtml"  

  •     };  
  •     AreaPartialViewLocationFormats = new[]  

  •     {  
  •         "~/Areas/{2}/Views/{1}/{0}.cshtml",  

  •         "~/Areas/{2}/Views/{1}/{0}.vbhtml",  
  •         "~/Areas/{2}/Views/Shared/{0}.cshtml",  

  •         "~/Areas/{2}/Views/Shared/{0}.vbhtml"  
  •     };  

  •   
  •     ViewLocationFormats = new[]  

  •     {  
  •         "~/Views/{1}/{0}.cshtml",  

  •         "~/Views/{1}/{0}.vbhtml",  
  •         "~/Views/Shared/{0}.cshtml",  

  •         "~/Views/Shared/{0}.vbhtml"  
  •     };  

  •     MasterLocationFormats = new[]  
  •     {  

  •         "~/Views/{1}/{0}.cshtml",  
  •         "~/Views/{1}/{0}.vbhtml",  

  •         "~/Views/Shared/{0}.cshtml",  
  •         "~/Views/Shared/{0}.vbhtml"  

  •     };  
  •     PartialViewLocationFormats = new[]  

  •     {  
  •         "~/Views/{1}/{0}.cshtml",  

  •         "~/Views/{1}/{0}.vbhtml",  
  •         "~/Views/Shared/{0}.cshtml",  

  •         "~/Views/Shared/{0}.vbhtml"  
  •     };  

  •   
  •     FileExtensions = new[]  

  •     {  
  •         "cshtml",  

  •         "vbhtml",  
  •     };  

  • }  
            public RazorViewEngine(IViewPageActivator viewPageActivator)
                : base(viewPageActivator)
            {
                AreaViewLocationFormats = new[]
                {
                    "~/Areas/{2}/Views/{1}/{0}.cshtml",
                    "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                    "~/Areas/{2}/Views/Shared/{0}.cshtml",
                    "~/Areas/{2}/Views/Shared/{0}.vbhtml"
                };
                AreaMasterLocationFormats = new[]
                {
                    "~/Areas/{2}/Views/{1}/{0}.cshtml",
                    "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                    "~/Areas/{2}/Views/Shared/{0}.cshtml",
                    "~/Areas/{2}/Views/Shared/{0}.vbhtml"
                };
                AreaPartialViewLocationFormats = new[]
                {
                    "~/Areas/{2}/Views/{1}/{0}.cshtml",
                    "~/Areas/{2}/Views/{1}/{0}.vbhtml",
                    "~/Areas/{2}/Views/Shared/{0}.cshtml",
                    "~/Areas/{2}/Views/Shared/{0}.vbhtml"
                };
    
                ViewLocationFormats = new[]
                {
                    "~/Views/{1}/{0}.cshtml",
                    "~/Views/{1}/{0}.vbhtml",
                    "~/Views/Shared/{0}.cshtml",
                    "~/Views/Shared/{0}.vbhtml"
                };
                MasterLocationFormats = new[]
                {
                    "~/Views/{1}/{0}.cshtml",
                    "~/Views/{1}/{0}.vbhtml",
                    "~/Views/Shared/{0}.cshtml",
                    "~/Views/Shared/{0}.vbhtml"
                };
                PartialViewLocationFormats = new[]
                {
                    "~/Views/{1}/{0}.cshtml",
                    "~/Views/{1}/{0}.vbhtml",
                    "~/Views/Shared/{0}.cshtml",
                    "~/Views/Shared/{0}.vbhtml"
                };
    
                FileExtensions = new[]
                {
                    "cshtml",
                    "vbhtml",
                };
            }

    すべてのアドレスパスがフォーマットされているのはよく知られているのではないでしょうか.ここでリストを使わずに配列を使う理由については、配列のアドレス効率がもっと高く、遍歴速度が速いと思います.
    さあ、「元凶」を探したら、おとなしく言うことを聞いて、どこへでも行かせてください.
    [csharp] view plain copy print ?
    namespace MvcApplicatin.Web.Mvc.ViewEngine  
  • {  

  •     public sealed class CustomViewEngine : RazorViewEngine  
  •     {  

  •   
  •         public CustomViewEngine()  

  •         {  
  •             ViewLocationFormats = new[]  

  •             {  
  •                 "~/Views/{1}/{0}.cshtml",  

  •                 "~/Views/Shared/{0}.cshtml",  
  •                 "~/CustomViewLocation/{1}/{0}.cshtml"  

  •             };  
  •         }  

  •         public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)  
  •         {  

  •             return base.FindView(controllerContext, viewName, masterName, useCache);  
  •         }  

  •     }  
  • }  
  • namespace MvcApplicatin.Web.Mvc.ViewEngine
    {
        public sealed class CustomViewEngine : RazorViewEngine
        {
    
            public CustomViewEngine()
            {
                ViewLocationFormats = new[]
                {
                    "~/Views/{1}/{0}.cshtml",
                    "~/Views/Shared/{0}.cshtml",
                    "~/CustomViewLocation/{1}/{0}.cshtml"
                };
            }
            public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
            {
                return base.FindView(controllerContext, viewName, masterName, useCache);
            }
        }
    }

    私が開発言語を使っているのはC#で、ビューはRazorなので、CustomViewLocationの下のビューを見つけるためにViewLocationFormatを少し修正しました.
    次は簡単です.元のビューエンジンを空にして、自分のビューエンジンをロードすればいいだけです.
    [csharp] view plain copy print ?
    protected void Application_Start()  
  • {  

  •     AreaRegistration.RegisterAllAreas();  
  •   

  •     ViewEngines.Engines.Clear();  
  •   

  •     ViewEngines.Engines.Add(new CustomViewEngine());  
  •   

  •     RegisterGlobalFilters(GlobalFilters.Filters);  
  •     RegisterRoutes(RouteTable.Routes);  

  • }  
            protected void Application_Start()
            {
                AreaRegistration.RegisterAllAreas();
    
                ViewEngines.Engines.Clear();
    
                ViewEngines.Engines.Add(new CustomViewEngine());
    
                RegisterGlobalFilters(GlobalFilters.Filters);
                RegisterRoutes(RouteTable.Routes);
            }