95992828九五至尊2

重写RazorViewEngine实现多要旨切换,area实现多元controller和文山会海view

一月 11th, 2019  |  九五至尊1老品牌值得

时常索要描述这样的花色社团

    在ASP.NET
MVC中来贯彻核心的切换一般有二种办法,一种是透过切换皮肤的css和js引用,一种就是由此重写视图引擎。通过重写视图引擎的措施越来越灵活,因为自身不但可以在不同主旨下面布局和体裁不平等,还可以够让不同的主题下边展现的数量条目不均等,就是说能够在少数核心下面添加一下个性化的事物。

~:.        //web根目录
├─.admin      //管理员效能目录
│  └─index.html    //管理员目录页面
├─.user                  //用户效能目录
│  └─index.html      //用户效用目录
└─index.html          //首页

   
本篇我将经过重写视图引擎的办法来展开出现说法,在这往日,我假使你早已具有了MVC的一些基础,系统登录后是默认主旨,当我们点击切换主旨之后,左边菜单栏的布局变了,右边内容的样式也变了,而地址栏是不变的。界面UI用的metronic,即便官网是收费的,可是在天朝,总是可以找到免费的。metronic是依据bootstrap的UI框架,官网地址:http://keenthemes.com/preview/metronic/

在平日的mvc之下,我们需要将各个controller和view都写在一定的页面中,这样所有的文本都堆砌在这六个目录中,

    大家先来看下效果:

对于常见的小型项目,这样也许是相比较便利的化解方案,但需要将项目目录进行精雕细刻的撤并的时候默认的mvc目录就

九五至尊1老品牌值得 1

没辙兑现咱们需要的职能了。

九五至尊1老品牌值得 2

貌似我们会采取二种办法来落实

   
在这边,我利用了分区域、分模块(按独立的作业职能区划)的格局,一个模块就是一个独门的dll,在此处Secom.Emx.Admin和Secom.Emx.History就是三个单身的模块,并各自创制了区域Admin和History,当然你可以在单独模块下面成立四个区域。

1.经过自定义路由+自定义视图引擎

 九五至尊1老品牌值得 3九五至尊1老品牌值得 4

2.用到area来对每个目录举行具体的田间管理

   
你会发觉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项目标指定目录下。

区别其他职能制止文件较多暴发歧义

九五至尊1老品牌值得 5

1.由此自定义路由+自定义视图引擎

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

第一定义路由规则,在档次目录下的App_Start/RouteConfig.cs文件中开展布局

九五至尊1老品牌值得 6

 1 public static void RegisterRoutes(RouteCollection routes)
 2         {
 3             routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
 4 
 5             //添加自定义的路由规则
 6             routes.MapRoute(
 7                 //根据约定,需要保证路由名的唯一性
 8                 name: "teacher",
 9                 //此处通过添加teacher部分来区分教师的功能页面
10                 url: "teacher/{controller}/{action}/{id}",
11                 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
12                 //此处由于多个路由规则都使用了名为Home的controller,所以需要
13                 //传入名称空间来保证控制器的唯一性
14                 namespaces:new string[] { "SCMS.Controllers.teacher" });
15             routes.MapRoute(
16                 name: "manager",
17                 url: "manager/{controller}/{action}/{id}",
18                 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
19                 namespaces: new string[] { "SCMS.Controllers.manager" });
20             routes.MapRoute(
21                 name: "admin",
22                 url: "admin/{controller}/{action}/{id}",
23                 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
24                 namespaces: new string[] { "SCMS.Controllers.admin" });
25             
26             //系统定义的路由规则
27             routes.MapRoute(
28                 name: "Default",
29                 url: "{controller}/{action}/{id}",
30                 defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
31                 namespaces: new string[] { "SCMS.Controllers" });
32         }            

    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" }
            );
        }
    }
}

布局如下的一个类,继承RazorViewEngine类,视同一律写ViewLocationFormats的内容

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

public class ViewEngine : RazorViewEngine
    {

        public ViewEngine()
        {
            ViewLocationFormats = new[]
            {
                "~/Views/{1}/{0}.cshtml",
                "~/Views/Shared/{0}.cshtml",
                "~/Views/admin/{1}/{0}.cshtml",
                "~/Views/teacher/{1}/{0}.cshtml",
                "~/Views/manager/{1}/{0}.cshtml"
            };
        }

    }

九五至尊1老品牌值得 7九五至尊1老品牌值得 8

扫除原有的视图引擎并将重写的视图引擎传入,文件地点为全局Global.asax文件

using System.Web.Mvc;

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

        public override void RegisterArea(AreaRegistrationContext context) 
        {
            context.MapRoute(
                "History_default",
                "History/{controller}/{action}/{id}",
                new { action = "Index", id = UrlParameter.Optional },
                namespaces:new string[1] { "Secom.Emx.History.Areas.History.Controllers" }
            );
        }
    }
}
 protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            //注意此处
            ViewEngines.Engines.Clear();
            ViewEngines.Engines.Add(new ViewEngine());
        }

View Code

基于网上教程经过尝试后发现能够落实自定义目录的目标,可是依照这里的view解析目录,系统默认提供的

    咱们先看下RazorViewEngine的本来构造函数如下:

剖析方法和自定义的辨析方法只有一个能担保访问成果,若有使用不当之处望周知。此处给出一个不算恰当

九五至尊1老品牌值得 9九五至尊1老品牌值得 10

的缓解方案,将直接存放在默认地点的首页也单独管理即可。然后去掉”~/Views/{1}/{0}.cshtml”项,加入

    public RazorViewEngine(IViewPageActivator viewPageActivator)  
        : base(viewPageActivator)  
    {  
        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"  
        };  
        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"  
        };  
        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"  
        };  

        ViewLocationFormats = new[]  
        {  
            "~/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"  
        };  
        PartialViewLocationFormats = new[]  
        {  
            "~/Views/{1}/{0}.cshtml",  
            "~/Views/{1}/{0}.vbhtml",  
            "~/Views/Shared/{0}.cshtml",  
            "~/Views/Shared/{0}.vbhtml"  
        };  

        FileExtensions = new[]  
        {  
            "cshtml",  
            "vbhtml",  
        };  
    }  

“~/Views/Home/{1}/{0}.cshtml”

View Code

至此,第一种方法已经竣工

   
然后新建CustomRazorViewEngine继承自RazorViewEngine,对View的路由规则举办了重写,既然能够重写路由规则,这表示,你可以随便定义规则,然后坚守自己定义的条条框框就足以了。需要小心的是,要注意路由数组中的顺序,查找视图时,是遵照前后相继依次查找的,当找到了视图就顿时回去,不会再去匹配前面的路由规则。为了提高路由查找效用,我这里删除了具有vbhtml的路由规则,因为我整整项目中都使用C#语言。

 2.运用area来对每个目录举办具体的保管

九五至尊1老品牌值得 11九五至尊1老品牌值得 12

经过第一种艺术虽能落实大家需要的机能,但是对于效能较多的系列以来对于每一个效用都需要独自处理,

using System.Web.Mvc;

namespace Secom.Emx.WebApp.Helper
{
    public class CustomRazorViewEngine : RazorViewEngine
    {
        public CustomRazorViewEngine(string theme)
        {
            if (!string.IsNullOrEmpty(theme))
            {
                AreaViewLocationFormats = new[]
                {
                       //themes
                       "~/themes/"+theme+"/views/Areas/{2}/{1}/{0}.cshtml",
                      "~/themes/"+theme+"/Shared/{0}.cshtml"

        "~/Areas/{2}/Views/{1}/{0}.cshtml",
        "~/Areas/{2}/Views/Shared/{0}.cshtml"
    };
                AreaMasterLocationFormats = new[]
                {
                             //themes
              "~/themes/"+theme+"/views/Areas/{2}/{1}/{0}.cshtml",
              "~/themes/"+theme+"/views/Areas/{2}/Shared/{0}.cshtml",
              "~/themes/"+theme+"/views/Shared/{0}.cshtml",

        "~/Areas/{2}/Views/{1}/{0}.cshtml",
        "~/Areas/{2}/Views/Shared/{0}.cshtml"
    };
                AreaPartialViewLocationFormats = new[]
                {
                            //themes
         "~/themes/"+theme+"/views/Shared/{0}.cshtml",

        "~/Areas/{2}/Views/{1}/{0}.cshtml",
        "~/Areas/{2}/Views/Shared/{0}.cshtml"
    };

                ViewLocationFormats = new[]
                {
                            //themes
          "~/themes/"+theme+"/views/{1}/{0}.cshtml",

        "~/Views/{1}/{0}.cshtml",
        "~/Views/Shared/{0}.cshtml"
    };
                MasterLocationFormats = new[]
                {
                            //themes
         "~/themes/"+theme+"/views/Shared/{0}.cshtml",

        "~/Views/{1}/{0}.cshtml",
        "~/Views/Shared/{0}.cshtml"
    };
                PartialViewLocationFormats = new[]
                {
                            //themes
        "~/themes/"+theme+"/views/Shared/{0}.cshtml",

        "~/Views/{1}/{0}.cshtml",
        "~/Views/Shared/{0}.cshtml"
    };

                FileExtensions = new[]{"cshtml"};
            }

        }
    }
}

这般需要重写大量的路由规则和view匹配规则,也可能是对mvc的刺探不够所以没察觉更好的章程,这里

View Code

就足以接纳area区域来对其目录结构举办保管,如下

九五至尊1老品牌值得 13

透过右键项目目录新建区域建立区域框架,然后成立了之类的目录结构

   
重写后,我们的路由规则将是这般的:当没有选用核心的情形下,沿用原来的路由规则,如果采取了焦点,则应用重写后的路由规则。

C:\USERS\IVES\DESKTOP\SCMS\SCMS\AREAS
├─admin
│  ├─Controllers
│  ├─Models
│  └─Views
│      ├─Home
│      └─Shared
├─manager
│  ├─Controllers
│  ├─Models
│  └─Views
│      └─Shared
└─teacher
    ├─Controllers
    ├─Models
    └─Views
        └─Shared

新的路由规则:在挑选了主旨的状态下,优先查找thems/核心名称/views/Areas/区域名称/控制器名称/视图名称.cshtml,假若找不到再依据默认的路由规则去找寻,也就是Areas/区域名称/Views/控制器名称/视图名称.cshtml。

此地我们得以窥见每个区域的目录结构树中均隐含独立的MVC的协会,我们只需要将相应的每一个索引的内容放入对应的区域即可

能够观看大家寻找模板页的章程也被改动了,所以对于一些通用的,只要换模板页就足以了,不需要丰盛view界面,因为指定核心下边找不到view会去默认主题下边找,而view界面会引用模板页的,对于一些个性化的事物,再去指定的主旨下面添加新的view,不知晓自家这么表述你有知道没,感觉比较饶,反正就是您可以按照你协调的规则去找视图,而不是asp.net
mvc默认的平整。

具体内容见下图

 九五至尊1老品牌值得 14

九五至尊1老品牌值得 15

    切换要旨View代码:

如图,大家只需要将原来平素写在品种路线下的连带内容一向写在此处对应area中即可,其他与原来的采纳办法没有其他区别

                <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;
                        切换主题&nbsp;&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中读取所选核心新闻,当库克ie中没有读取到主题记录时,则从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();
        }
    }
}

记录下来,留待后查,同时有利于客人。

九五至尊1老品牌值得,    Utils类:

联系自身举办互换。renhanlinbsl@163.com

九五至尊1老品牌值得 16九五至尊1老品牌值得 17

2017.11.15

using System.Configuration;
using System.Web.Mvc;

namespace Secom.Emx.WebApp.Helper
{
    public class Utils
    {
        private static string _themeName;

        public static string ThemeName
        {
            get
            {
                if (!string.IsNullOrEmpty(_themeName))
                {
                    return _themeName;
                }
                //模板风格
                _themeName =string.IsNullOrEmpty(ConfigurationManager.AppSettings["Theme"])? "" : ConfigurationManager.AppSettings["Theme"];
                return _themeName;
            }
        }
        public static void ResetRazorViewEngine(string themeName)
        {
            themeName = string.IsNullOrEmpty(themeName) ? Utils.ThemeName : themeName;
            if (!string.IsNullOrEmpty(themeName))
            {
                ViewEngines.Engines.Clear();
                ViewEngines.Engines.Add(new CustomRazorViewEngine(themeName));
            }
        }
    }
}

15:37

View Code

    
实现形式实际上是太简单,简单得我不理解什么表明才好,我或者记下来,方便有亟待的人得以查看,希望得以帮到你们。由于品种引入了庞然大物的各个有关文书以致文件相比大,网速原因无法上传源码还望见谅!

Your Comments

近期评论

    功能


    网站地图xml地图