制作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

asp.net mvc中换肤机制类库 ThemedViewEngines的更多相关文章

  1. 转载ASP.NET MVC中Session的处理机制

    本文章转载自 http://www.cnblogs.com/darrenji/p/3951065.html ASP.NET MVC中的Session以及处理方式   最近在ASP.NET MVC项目中 ...

  2. Asp.net Mvc中利用ValidationAttribute实现xss过滤

    在网站开发中,需要注意的一个问题就是防范XSS攻击,Asp.net mvc中已经自动为我们提供了这个功能.用户提交数据时时,在生成Action参数的过程中asp.net会对用户提交的数据进行验证,一旦 ...

  3. 【ASP.NET MVC系列】浅谈jqGrid 在ASP.NET MVC中增删改查

    ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...

  4. 如何在 ASP.NET MVC 中集成 AngularJS(1)

    介绍 当涉及到计算机软件的开发时,我想运用所有的最新技术.例如,前端使用最新的 JavaScript 技术,服务器端使用最新的基于 REST 的 Web API 服务.另外,还有最新的数据库技术.最新 ...

  5. Asp.Net MVC中DropDownListFor的用法(转)

    2016.03.04 扩展:如果 view中传入的是List<T>类型 怎么使用 DropList 既然是List<T> 那么我转化成 T  List<T>的第一个 ...

  6. Asp.Net MVC中DropDownListFor的用法

    在Asp.Net MVC中可以用DropDownListFor的方式来让用户选择已定列表中的一个数值.用法不复杂,这里简单做一个记录. 首先我们要定义一个 Model ,用户在 DropDownLis ...

  7. 在ASP.Net MVC 中,如何在Global.asax中配置一个指向Area内部的默认Route

    ASP.Net MVC 中配置Route的时候可以设置一个默认的Route. 比如我要在输入http://localhost的时候默认进入http://localhost/home/index.可以在 ...

  8. 转:Asp.Net MVC中DropDownListFor的用法

    在Asp.Net MVC中可以用DropDownListFor的方式来让用户选择已定列表中的一个数值.用法不复杂,这里简单做一个记录. 首先我们要定义一个 Model ,用户在 DropDownLis ...

  9. 在ASP.NET MVC中使用IIS级别的URL Rewrite

    原文 在ASP.NET MVC中使用IIS级别的URL Rewrite 大约一年半前,我在博客上写过一系列关于URL Rewrite的文章(2.3.4),把ASP.NET平台上进行URL Rewrit ...

  10. ASP.NET MVC中对Model进行分步验证的解决方法

    原文:ASP.NET MVC中对Model进行分步验证的解决方法 在我之前的文章:ASP.NET MVC2.0结合WF4.0实现用户多步注册流程中将一个用户的注册分成了四步,而这四个步骤都是在完善一个 ...

随机推荐

  1. Java常见面试真题之中级进阶(List篇)

    前言 本来想着给自己放松一下,刷刷博客,突然被几道面试题难倒!获取一个类Class对象的方式有哪些?ArrayList 和 LinkedList 的区别有哪些?用过 ArrayList 吗?说一下它有 ...

  2. Surface pro 11二合一平板参数调研

    最近研究了下Surface pro 11,记录下相关参数,矩阵我以表格列出来.可能不够细,大家作个参考吧 模块 技术项 参数 备注 处理器 型号 Snapdragon X Elite(X1E-80-1 ...

  3. pyenv-win-master\pyenv-win\libexec\pyenv-install.vbs(161, 5) Microsoft VBScript 运行时错误: 文件未找到

    Windows 10 运行 pyenv install 3.11.2 提示 pyenv-win-master\pyenv-win\libexec\pyenv-install.vbs(161, 5) M ...

  4. IPC-7093A-CN 中文 2020底部端子元器件(BTCs)设计和组装工艺的实施

    IPC-7093A 标准为实施底部端子元器件(BTCs)提供了基本的设计和组装指南.具体而言,IPC-7093A 提供了与 BTCs 相关的关键设计.材料.组装.检查.维修.质量和可靠性问题的指南. ...

  5. Tensorflow/Keras、Pytorch 杂记

    Tensorflow/Keras 直接从文件生成图片数据 ImageDataGenerator,循环生成图片,在重复生成图片之前,会把所有图片都遍历一遍.而且如果图片总量不是生成批量的倍数的话,在生成 ...

  6. elasticsearch之python操作(非原生)

    elasticsearch 模块 Elasticsearch低级客户端.提供从Python到ES REST端点的直接映射. 连接集群节点 指定连接 es = Elasticsearch( ['172. ...

  7. 什么是.NET的强类型字符串(Strongly typed string)?

    在.NET中,强类型字符串(Strongly typed string)并不是一个官方的概念,是指使用特定的结构来表示某种类型字符串数据的编码实践.类似于枚举,可以提供编译时检查类型,减少运行时错误, ...

  8. Nuxt.js 应用中的 error 事件钩子

    title: Nuxt.js 应用中的 error 事件钩子 date: 2024/12/3 updated: 2024/12/3 author: cmdragon excerpt: 在任何 Web ...

  9. Javascript 常用封装(二)

    1.字符串占位宽度 计算占位宽度:字符串的占位宽度除了涉及到具体的字符串内容,还与字体大小有关,可以将其放入Dom中来获取实际占位宽度 //计算字符串的占位宽度 function getTextWid ...

  10. FineReport取消强制分页和调整宽度的设置方法

    在decision里,找到管理系统-目录管理,打开相应挂载的报表,在参数设置里,添加以下内容: _bypagesize_ 字符串 false