[转]ASP.NET MVC Dynamic Themes
本文转自:http://www.codeproject.com/Articles/32847/ASP-NET-MVC-Dynamic-Themes
Introduction
I really needed to enable themes for my application, and I found an interesting article about it by Chris Pietschmann. In my point of view, the only problem with his approach is that you need to repeat each page for all themes. Well, I only want to create one page per theme, and have a master page and CSS files for each theme.
Using the code
For this project, I made some assumptions:
- The master page for each theme has the name Site.Master.
- The master page file and CSS files will be placed on a folder with the name of the theme.
- All the theme folders will be placed in the Content folder.
The file structure will be like this:
Now, let’s write a custom View Engine that will inherit from WebFormViewEngine
. This code is only a sketch of what I want to implement. For instance, I want to save the user theme selection so that, in the next login, the user has his option set.

public class ThemeViewEngine : WebFormViewEngine
{
public ThemeViewEngine()
{
base.ViewLocationFormats = new string[] {
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx"
}; base.MasterLocationFormats = new string[] {
"~/Content/{2}/Site.master"
}; base.PartialViewLocationFormats = new string[] {
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx"
};
} public override ViewEngineResult FindView(ControllerContext controllerContext,
string viewName, string masterName)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (string.IsNullOrEmpty(viewName))
{
throw new ArgumentException("Value is required.", "viewName");
} string themeName = this.GetThemeToUse(controllerContext); string[] searchedViewLocations;
string[] searchedMasterLocations; string controllerName =
controllerContext.RouteData.GetRequiredString("controller"); string viewPath = this.GetViewPath(this.ViewLocationFormats, viewName,
controllerName, out searchedViewLocations);
string masterPath = this.GetMasterPath(this.MasterLocationFormats, viewName,
controllerName, themeName, out searchedMasterLocations); if (!(string.IsNullOrEmpty(viewPath)) &&
(!(masterPath == string.Empty) || string.IsNullOrEmpty(masterName)))
{
return new ViewEngineResult(
(this.CreateView(controllerContext, viewPath, masterPath)), this);
}
return new ViewEngineResult(
searchedViewLocations.Union<string>(searchedMasterLocations));
} public override ViewEngineResult FindPartialView(ControllerContext controllerContext,
string partialViewName)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (string.IsNullOrEmpty(partialViewName))
{
throw new ArgumentException("Value is required.", partialViewName);
} string themeName = this.GetThemeToUse(controllerContext); string[] searchedLocations; string controllerName = controllerContext.RouteData.GetRequiredString("controller"); string partialPath = this.GetViewPath(this.PartialViewLocationFormats,
partialViewName, controllerName, out searchedLocations); if (string.IsNullOrEmpty(partialPath))
{
return new ViewEngineResult(searchedLocations);
}
return new ViewEngineResult(this.CreatePartialView(controllerContext,
partialPath), this);
} private string GetThemeToUse(ControllerContext controllerContext)
{
if (controllerContext.HttpContext.Request.QueryString.AllKeys.Contains("theme"))
{
string themeName = controllerContext.HttpContext.Request.QueryString["theme"];
controllerContext.HttpContext.Session.Add("Theme", themeName);
}
else if (controllerContext.HttpContext.Session["Theme"] == null)
{
controllerContext.HttpContext.Session.Add("Theme", "Default");
}
return controllerContext.HttpContext.Session["Theme"].ToString();
} private string GetViewPath(string[] locations, string viewName,
string controllerName, out string[] searchedLocations)
{
string path = null; searchedLocations = new string[locations.Length]; for (int i = 0; i < locations.Length; i++)
{
path = string.Format(CultureInfo.InvariantCulture, locations[i],
new object[] { viewName, controllerName });
if (this.VirtualPathProvider.FileExists(path))
{
searchedLocations = new string[0];
return path;
}
searchedLocations[i] = path;
}
return null;
} private string GetMasterPath(string[] locations, string viewName,
string controllerName, string themeName, out string[] searchedLocations)
{
string path = null; searchedLocations = new string[locations.Length]; for (int i = 0; i < locations.Length; i++)
{
path = string.Format(CultureInfo.InvariantCulture, locations[i],
new object[] { viewName, controllerName, themeName });
if (this.VirtualPathProvider.FileExists(path))
{
searchedLocations = new string[0];
return path;
}
searchedLocations[i] = path;
}
return null;
}
}
To finish this sample, just change the global.asax, removing all engines from the View Engine and adding the custom one:
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes); ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new ThemeViewEngine());
}
Well, hope that’s useful.
License
This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)
[转]ASP.NET MVC Dynamic Themes的更多相关文章
- 七天学会ASP.NET MVC(七)——创建单页应用
系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...
- 微冷的雨ASP.NET MVC之葵花宝典(MVC)
微冷的雨ASP.NET MVC之葵花宝典 By:微冷的雨 第一章 ASP.NET MVC的请求和处理机制. 在MVC中: 01.所有的请求都要归结到控制器(Controller)上. 02.约定优于配 ...
- 7 天玩转 ASP.NET MVC — 第 7 天
目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 今天是开心的一天.因为我们终于来到了系列学习的最后一节.我相信你喜欢之前的课程,并从中学到了许多. ...
- Bootstrap 与 ASP.NET MVC 4 不使用 NuGet Package 笔记
转自 http://www.mytecbits.com/microsoft/dot-net/bootstrap-with-asp-net-mvc-4-step-by-step 单位最近做了一个Boot ...
- BrnShop开源网上商城第二讲:ASP.NET MVC框架
在团队设计BrnShop的web项目之初,我们碰到了两个问题,第一个是数据的复用和传递,第二个是大mvc框架和小mvc框架的选择.下面我依次来说明下. 首先是数据的复用和传递:对于BrnShop的每一 ...
- 返璞归真 asp.net mvc (9) - asp.net mvc 3.0 新特性之 View(Razor)
原文:返璞归真 asp.net mvc (9) - asp.net mvc 3.0 新特性之 View(Razor) [索引页][源码下载] 返璞归真 asp.net mvc (9) - asp.ne ...
- 【ASP.NET】第一个ASP.NET MVC应用程序
本系列目录:ASP.NET MVC4入门到精通系列目录汇总 开发流程 新建Controller 创建Action 根据Action创建View 在Action获取数据并生产ActionResult传递 ...
- [转]Using the HTML5 and jQuery UI Datepicker Popup Calendar with ASP.NET MVC - Part 4
本文转自:http://www.asp.net/mvc/overview/older-versions/using-the-html5-and-jquery-ui-datepicker-popup-c ...
- 七天学会ASP.NET MVC(七)——创建单页应用 【转】
http://www.cnblogs.com/powertoolsteam/p/MVC_Seven.html 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学 ...
随机推荐
- Validating HTTP data with Play
Validations ensure that the data has certain values or meets specific requirements. You can use vali ...
- 关于HTML面试题汇总之visibility
一.页面可见性(visibility) 主要提供两个属性,一个事件(都在document对象上):1. 属性: 1.1. hidden:获取或设置当前页面的可见性,boolean值: 1.2 ...
- Rotating Image Slider - 图片旋转切换特效
非常炫的图片旋转滑动特效,相信会给你留下深刻印象.滑动图像时,我们会稍稍旋转它们并延缓各元素的滑动.滑块的不寻常的形状是由一些预先放置的元素和使用边框创建.另外支持自动播放选项,鼠标滚轮的功能. 在线 ...
- 你会喜欢的25个创意的扁平化 LOGO 设计
扁平设计的风暴席卷了整个设计领域,它不仅影响网页设计,也影响了用户界面和标志设计.最近,我们看到了很多大公司,如谷歌和必应开始使用扁平设计的标识. 一个 LOGO 应该简单,显眼和精美,以适应产品的整 ...
- Sublime text 3 快捷键的使用
快捷键的便捷使用: ctr+shift+n:打开新的sublime text ctr+shift+w:关闭sublime text ctr+o:打开 某个文件 ctrl+n:新建一个文本 ctrl+w ...
- 使用nodejs+express+socketio+mysql搭建聊天室
使用nodejs+express+socketio+mysql搭建聊天室 nodejs相关的资料已经很多了,我也是学习中吧,于是把socket的教程看了下,学着做了个聊天室,然后加入简单的操作mysq ...
- Sap 常用Function 说明
函数名 描述 SD_VBAP_READ_WITH_VBELN 根据销售订单读取表vbap中的信息EDIT_LINES 把READ_TEXT返回的LINES中的行按照TDFORMAT=“*”重新组织VI ...
- 转载:kafka参数详解
原文:http://kafka.apache.org/documentation.html ############################# System ################# ...
- atitit.userService 用户系统设计 v4 q316 .doc
atitit.userService 用户系统设计 v4 q316 .doc 1. 新特性1 2. Admin login1 3. 用户注册登录2 3.1. <!-- 会员注册使用 --> ...
- Sharepoint学习笔记—习题系列--70-576习题解析 -(Q13-Q15)
Question 13 You are designing a SharePoint 2010 site. You need to design the site to meet all the fo ...