asp.net mvc中换肤机制类库 ThemedViewEngines

制作blog系统或者通用cms系统的时候,我们经常会用到Theme功能。asp.net mvc中的一种实现方式,是继承实现RazorViewEngine即可。

这是在GitHub中找到的一个示例:https://github.com/benedict-chan/ThemedViewEngines

结构如下图:

实现的核心代码ThemedRazorViewEngine.cs:


using System;
using System.Web.Mvc;

namespace ThemedViewEngines
{
    public class ThemedRazorViewEngine : RazorViewEngine
    {
        private readonly IThemeSelectorService _themeSelectorService;
        public string DefaultMasterName { get; set; }
        public ThemedRazorViewEngine(IThemeSelectorService themeSelectorService)
            : base()
        {
            DefaultMasterName = "_Layout";
            this._themeSelectorService = themeSelectorService;

            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",

                "~/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",

                "~/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",

                "~/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",

                "~/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",

                "~/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",

                "~/Views/{1}/{0}.cshtml",
                "~/Views/{1}/{0}.vbhtml",
                "~/Views/Shared/{0}.cshtml",
                "~/Views/Shared/{0}.vbhtml"
            };
            FileExtensions = new[]
            {
                "cshtml",
                "vbhtml",
            };
        }
        protected override IView CreatePartialView(ControllerContext controllerContext, string partialPath)
        {
            string replacedPartialPath = GetThemedPath(partialPath);
            return base.CreatePartialView(controllerContext, replacedPartialPath);
        }
        protected override IView CreateView(ControllerContext controllerContext, string viewPath, string masterPath)
        {
            string replacedViewPath = GetThemedPath(viewPath);
            string replacedMasterPath = GetThemedPath(masterPath);
            return base.CreateView(controllerContext, replacedViewPath, replacedMasterPath);
        }
        protected override bool FileExists(ControllerContext controllerContext, string virtualPath)
        {
            string replacedVirtualPath = GetThemedPath(virtualPath);
            return base.FileExists(controllerContext, replacedVirtualPath);
        }
        public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
        {
            var themeName = this._themeSelectorService.GetThemeName();
            if (!string.IsNullOrEmpty(themeName) && string.IsNullOrEmpty(masterName))
            {
                //In case if we have a theme, and the request view is not found in the theme folder (i.e. we will use the default view), 
                // we will not be able to locate the theme's master page via _ViewStart (as the view is now in the default "theme" tree )
                //Therefore we have to manually locate the Master page name here
                masterName = DefaultMasterName;
            }
            return base.FindView(controllerContext, viewName, masterName, false);
        }
        private string GetThemedPath(string originalPath)
        {
            var replacedPath = originalPath;
            var themeName = this._themeSelectorService.GetThemeName();
            if (!string.IsNullOrEmpty(themeName))
            {
                string replaceText = string.Format("Themes/{0}", themeName);
                replacedPath = originalPath.Replace("#@", replaceText);
            }
            return replacedPath;
        }
    }
}

  

ConfigThemeService.cs的代码


 1 namespace ThemedViewEngines
 2 {
 3     public class ConfigThemeService : IThemeSelectorService
 4     {
 5         public string GetThemeName()
 6         {
 7             return ConfigurationManager.AppSettings["ThemeName"] ?? string.Empty;
 8         }
 9         public void SetThemeName(string themeName)
10         {
11             throw new NotSupportedException();
12         }
13 
14     }
15 }

IThemeSelectorService.cs的代码:

 1 namespace ThemedViewEngines
 2 {
 3     public interface IThemeSelectorService
 4     {
 5         /// <summary>
 6         /// 获取Theme名称
 7         /// </summary>
 8         /// <returns></returns>
 9         string GetThemeName();
10         /// <summary>
11         /// 设置主题名称
12         /// </summary>
13         /// <param name="themeName"></param>
14         void SetThemeName(string themeName);
15     }
16 }

CookieThemeService.cs的代码


 1 using System;
 2 using System.Web;
 3 
 4 namespace ThemedViewEngines
 5 {
 6     public class CookieThemeService : IThemeSelectorService
 7     {
 8         public string GetThemeName()
 9         {
10             var cookie = HttpContext.Current.Request.Cookies["ThemeName"];
11             if (cookie != null)
12                 return cookie.Value;
13             return string.Empty;
14         }
15 
16         public void SetThemeName(string themeName)
17         {
18             throw new System.NotImplementedException();
19         }
20     }
21 }

调用方式:


1、新建mvc项目

2、根据上图中的示例建立Themes文件夹,Themes下面新建blue和red文件夹,然后分别把Views下的文件复制到blue和red中(主要是web.config一定要复制过去,不然没有智能提示

3、添加引用ThemedViewEngines类库

4、在global文件的Application_Start方法下添加:

1 ViewEngines.Engines.Clear();
2 //用 Web.config 配置 theme 的写法
3 ViewEngines.Engines.Add(new ThemedRazorViewEngine(new ConfigThemeService()));
4 //用cookie配置theme的写法
5 //ViewEngines.Engines.Add(new ThemedRazorViewEngine(new CookieThemeService()));

5、在Web.config的appSettings节点下添加:

    <!--Theme配置-->
    <add key="ThemeName" value="blue" />
    <!--Theme配置 end-->

6、运行项目即可。

Demo下载


点击下载Demo

原文地址:https://www.cnblogs.com/wxb8/p/5725028.html