本文转自: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.

Hide    Shrink     Copy Code
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:

Hide    Copy Code
protected void Application_Start()
{
RegisterRoutes(RouteTable.Routes); ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new ThemeViewEngine());
}

Well, hope that’s useful.

&amp;amp;lt;a href="http://pubads.g.doubleclick.net/gampad/jump?iu=/6839/lqm.codeproject.site/Web-Development/ASP-NET/General&amp;amp;amp;sz=300x250&amp;amp;amp;c=361649"&amp;amp;gt;&amp;amp;lt;img src="http://pubads.g.doubleclick.net/gampad/ad?iu=/6839/lqm.codeproject.site/Web-Development/ASP-NET/General&amp;amp;amp;sz=300x250&amp;amp;amp;c=361649" width="300px" height="250px" target="_blank"/&amp;amp;gt;&amp;amp;lt;/a&amp;amp;gt;

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的更多相关文章

  1. 七天学会ASP.NET MVC(七)——创建单页应用

    系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学会ASP.NET MVC (二)——ASP.NET MVC 数据传递 七天学会ASP.NET MVC (三)— ...

  2. 微冷的雨ASP.NET MVC之葵花宝典(MVC)

    微冷的雨ASP.NET MVC之葵花宝典 By:微冷的雨 第一章 ASP.NET MVC的请求和处理机制. 在MVC中: 01.所有的请求都要归结到控制器(Controller)上. 02.约定优于配 ...

  3. 7 天玩转 ASP.NET MVC — 第 7 天

    目录 第 1 天 第 2 天 第 3 天 第 4 天 第 5 天 第 6 天 第 7 天 0. 前言 今天是开心的一天.因为我们终于来到了系列学习的最后一节.我相信你喜欢之前的课程,并从中学到了许多. ...

  4. Bootstrap 与 ASP.NET MVC 4 不使用 NuGet Package 笔记

    转自 http://www.mytecbits.com/microsoft/dot-net/bootstrap-with-asp-net-mvc-4-step-by-step 单位最近做了一个Boot ...

  5. BrnShop开源网上商城第二讲:ASP.NET MVC框架

    在团队设计BrnShop的web项目之初,我们碰到了两个问题,第一个是数据的复用和传递,第二个是大mvc框架和小mvc框架的选择.下面我依次来说明下. 首先是数据的复用和传递:对于BrnShop的每一 ...

  6. 返璞归真 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 ...

  7. 【ASP.NET】第一个ASP.NET MVC应用程序

    本系列目录:ASP.NET MVC4入门到精通系列目录汇总 开发流程 新建Controller 创建Action 根据Action创建View 在Action获取数据并生产ActionResult传递 ...

  8. [转]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 ...

  9. 七天学会ASP.NET MVC(七)——创建单页应用 【转】

    http://www.cnblogs.com/powertoolsteam/p/MVC_Seven.html 系列文章 七天学会ASP.NET MVC (一)——深入理解ASP.NET MVC 七天学 ...

随机推荐

  1. 太可爱了!CSS3 & SVG 制作的米老鼠钟表

    米老鼠是大家非常熟悉的迪斯尼动画形象.这是一个可爱的效果,结合 CSS & SVG 图形实现的米老鼠钟表效果.Web 技术让很多生活中的事物都能搬到网上去,后面的推荐阅读也有很多的效果,感兴趣 ...

  2. linux系统免密码登陆

    有两台机器,系统都是CentOS6.5,IP分别为192.168.2.150,192.168.2.151.现在150需要SSH免密码登陆151. 在150上面执行命令,当前登录用户是root: # s ...

  3. [IOS]edgesForExtendedLayout、automaticallyAdjustsScrollViewInsets

    在IOS7以后 ViewController 开始使用全屏布局的,而且是默认的行为通常涉及到布局 就离不开这个属性 edgesForExtendedLayout,它是一个类型为UIExtendedEd ...

  4. Android Studio简单设置

    IDE外观&行为 修改主题,修改全局字体 修改主题,想用炫酷的深色主题,就改成Darcula吧:字体的话,选一个带中文的,要不然会有很多口口,我这里用Microsoft YaHei UI,很不 ...

  5. Android 采用post方式提交数据到服务器

    接着上篇<Android 采用get方式提交数据到服务器>,本文来实现采用post方式提交数据到服务器 首先对比一下get方式和post方式: 修改布局: <LinearLayout ...

  6. HTTPS时代全面到来,你准备好了吗?

    近一年可能有很多朋友发现在使用百度搜索时,是这个样子的 如我们所见,浏览器地址栏里的HTTP可能将成为永远的过去时,取而代之的是更安全的HTTPS. 首先,HTTPS是什么? HTTPS是Http O ...

  7. 如何为Swift进行宏定义

    这阵子一直在自学Swift, 因为之前iOS的开发一直用Objective-C, 所以习惯了C语言那种宏定义方式, Swift作为一款更加安全的语言, 放弃了C语言中的宏定义, 有效的防止预编译时代码 ...

  8. 网络邂逅&网络异步请求

    什么是卡,网络慢,且你只能等着它加载完不能做别的事 这里便引申出网络异步请求的概念 #import "ViewController.h" @interface ViewContro ...

  9. GCD中的dispatch_barrier_async函数的使用(栅栏函数)

    <一>什么是dispatch_barrier_async函数 毫无疑问,dispatch_barrier_async函数的作用与barrier的意思相同,在进程管理中起到一个栅栏的作用,它 ...

  10. vs2012中使用Icenium开发应用

    Developing a Cross Platform Mobile App in Visual Studio using JavaScript & HTML5 http://www.dotn ...