ASP.NET MVC 重写RazorViewEngine实现多主题切换

简介:

在ASP.NET MVC中来实现主题的切换一般有两种方式,一种是通过切换皮肤的css和js引用,一种就是通过重写视图引擎。通过重写视图引擎的方式更加灵活,因为我不仅可以在不同主题下面布局和样式不一样,还可以让不同的主题下面显示的数据条目不一致,就是说可以在某些主题下面添加一下个性化的东西。

    本篇我将通过重写视图引擎的方式来进行演示,在这之前,我假设你已经具备了MVC的一些基础,系统登录后是默认主题,当我们点击切换主题之后,左侧菜单栏的布局变了,右侧内容的样式也变了,而地址栏是不变的。界面UI用的metronic,虽然官网是收费的,但是在天朝,总是可以找到免费的。metronic是基于bootstrap的UI框架,官网地址:http://keenthemes.com/preview/metronic/

    我们先来看下效果:

    在这里,我使用了分区域、分模块(按独立的业务功能划分)的方式,一个模块就是一个独立的dll,在这里Secom.Emx.Admin和Secom.Emx.History就是两个独立的模块,并分别创建了区域Admin和History,当然你可以在独立模块下面创建多个区域。

 

    你会发现Secom.Emx.Admin模型下面的Areas目录和Secom.Emx.WebApp中的目录是一模一样的,其实我最初不想在模块项目中添加任何的View,但是为了方便独立部署还是加了。右键单击项目Secom.Emx.Admin,选择“属性”——“生成事件”添加如下代码:

xcopy /e/r/y $(ProjectDir)Areas\Admin\Views $(SolutionDir)Secom.Emx.WebApp\Areas\Admin\Views

    这命令很简单,其实就是当编译项目Secom.Emx.Admin的时候,将项目中的Views复制到Secom.Emx.WebApp项目的指定目录下。

    区域配置文件我放置到了Secom.Emx.WebApp中,其实你完全可以独立放置到一个类库项目中,因为注册区域路由的后,项目最终会寻找bin目录下面所有继承了AreaRegistration类的,然后让WebApp引用这个类库项目,Secom.Emx.WebApp项目添加Secom.Emx.Admin、Secom.Emx.History的引用。

    AdminAreaRegistration代码如下:

复制代码
using System.Web.Mvc;

namespace Secom.Emx.WebApp
{
    public class AdminAreaRegistration : AreaRegistration 
    {
        public override string AreaName 
        {
            get 
            {
                return "Admin";
            }
        }

        public override void RegisterArea(AreaRegistrationContext context) 
        {
            context.MapRoute(
                "Admin_default",
                "Admin/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional },
                namespaces:new string[1] { "Secom.Emx.Admin.Areas.Admin.Controllers" }
            );
        }
    }
}
复制代码

    注意命名空间和后面添加的 namespaces:new string[1] { "Secom.Emx.Admin.Areas.Admin.Controllers" },这个命名空间就是独立模块Secom.Emx.Admin下面的控制器所在的命名空间。HistoryAreaRegistration代码如下:

  View Code

    我们先看下RazorViewEngine的原始构造函数如下:

  View Code

    然后新建CustomRazorViewEngine继承自RazorViewEngine,对View的路由规则进行了重写,既然可以重写路由规则,那意味着,你可以任意定义规则,然后遵守自己定义的规则就可以了。需要注意的是,要注意路由数组中的顺序,查找视图时,是按照前后顺序依次查找的,当找到了视图就立即返回,不会再去匹配后面的路由规则。为了提升路由查找效率,我这里删除了所有vbhtml的路由规则,因为我整个项目中都采用C#语言。

  View Code

    重写后,我们的路由规则将是这样的:当没有选择主题的情况下,沿用原来的路由规则,如果选择了主题,则使用重写后的路由规则。

新的路由规则:在选择了主题的情况下,优先查找thems/主题名称/views/Areas/区域名称/控制器名称/视图名称.cshtml,如果找不到再按照默认的路由规则去寻找,也就是Areas/区域名称/Views/控制器名称/视图名称.cshtml。

可以看到我们查找模板页的方式也被修改了,所以对于一些通用的,只要换模板页就可以了,不需要添加view界面,因为指定主题下面找不到view会去默认主题下面找,而view界面会引用模板页的,对于一些个性化的东西,再去指定的主题下面添加新的view,不知道我这样表述你有明白没,感觉比较饶,反正就是你可以按照你自己的规则去找视图,而不是asp.net mvc默认的规则。

 

    切换主题View代码:

复制代码
                <div class="btn-group">
                    <button type="button" class="btn btn-circle btn-outline red dropdown-toggle" data-toggle="dropdown">
                        <i class="fa fa-plus"></i>&nbsp;
                        <span class="hidden-sm hidden-xs">切换主题&nbsp;</span>&nbsp;
                        <i class="fa fa-angle-down"></i>
                    </button>
                    <ul class="dropdown-menu" role="menu">
                        <li>
                            <a href="javascript:setTheme('default')">
                                <i class="icon-docs"></i> 默认主题
                            </a>
                        </li>
                        <li>
                            <a href="javascript:setTheme('Blue')">
                                <i class="icon-tag"></i> 蓝色主题
                            </a>
                        </li>
                    </ul>
                </div>
        <script type="text/javascript">
           function setTheme(themeName)
            {
               window.location.href = "/Home/SetTheme?themeName=" + themeName + "&href=" + window.location.href;
            }
        </script>
复制代码

    当用户登录成功的时候,从Cookie中读取所选主题信息,当Cookie中没有读取到主题记录时,则从Web.config配置文件中读取配置的主题名称,如果都没有读取到,则说明是默认主题,沿用原有的视图引擎规则。在后台管理界面,每次选择了主题,我都将主题名称存储到Cookie中,默认保存一年,这样当下次再登录的时候,就能够记住所选的主题信息了。

复制代码
using System;
using System.Web.Mvc;
using Secom.Emx.WebApp.Helper;
using System.Web;
using Secom.Emx.Common.Controllers;

namespace Secom.Emx.WebApp.Controllers
{
    public class HomeController : BaseController
    {
        string themeCookieName = "Theme";
        public ActionResult Index()
        {
            ViewData["Menu"] = GetMenus();
            return View();
        }
        public ActionResult SetTheme(string themeName,string href)
        {
            if (!string.IsNullOrEmpty(themeName))
            {
                Response.Cookies.Set(new HttpCookie(themeCookieName, themeName) { Expires = DateTime.Now.AddYears(1) });
            }
            else
            {
                themeName = Request.Cookies[themeCookieName].Value ?? "".Trim();
            }
            Utils.ResetRazorViewEngine(themeName);
            return string.IsNullOrEmpty(href)? Redirect("~/Home/Index"):Redirect(href);
        }
        public ActionResult Login()
        {
            string themeName = Request.Cookies[themeCookieName].Value ?? "".Trim();
            if (!string.IsNullOrEmpty(themeName))
            {
                Utils.ResetRazorViewEngine(themeName);
            }
            return View();
        }
    }
}
复制代码

    Utils类:

  View Code

     实现方式实在是太简单,简单得我不知道如何表述才好,我还是记下来,方便有需要的人可以查阅,希望可以帮到你们。由于项目引入了庞大的各种相关文件以致文件比较大,网速原因无法上传源码还望见谅!

本文转自邹琼俊博客园博客,原文链接:http://www.cnblogs.com/jiekzou/p/7084827.html,如需转载请自行联系原作者

相关文章
|
3月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
38 0
|
30天前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
28 0
|
30天前
mvc.net分页查询案例——mvc-paper.css
mvc.net分页查询案例——mvc-paper.css
5 0
|
1月前
|
开发框架 前端开发 .NET
C# .NET面试系列六:ASP.NET MVC
<h2>ASP.NET MVC #### 1. MVC 中的 TempData\ViewBag\ViewData 区别? 在ASP.NET MVC中,TempData、ViewBag 和 ViewData 都是用于在控制器和视图之间传递数据的机制,但它们有一些区别。 <b>TempData:</b> 1、生命周期 ```c# TempData 的生命周期是短暂的,数据只在当前请求和下一次请求之间有效。一旦数据被读取,它就会被标记为已读,下一次请求时就会被清除。 ``` 2、用途 ```c# 主要用于在两个动作之间传递数据,例如在一个动作中设置 TempData,然后在重定向到另
95 5
|
3月前
|
XML 前端开发 定位技术
C#(NET Core3.1 MVC)生成站点地图(sitemap.xml)
C#(NET Core3.1 MVC)生成站点地图(sitemap.xml)
25 0
|
3月前
|
前端开发
.net core mvc获取IP地址和IP所在地(其实是百度的)
.net core mvc获取IP地址和IP所在地(其实是百度的)
123 0
|
5月前
|
开发框架 自然语言处理 前端开发
基于ASP.NET MVC开发的、开源的个人博客系统
基于ASP.NET MVC开发的、开源的个人博客系统
51 0
|
8月前
|
SQL 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(完:内附源码)
经过一段时间的准备,【ASP.NET Core MVC开发实战之商城系统】已经完成,目前代码已开发完成,先将全部内容整理分享,如有不足之处,还请指正。
106 0