ASP.NET MVC:多模板支持

简介: 原文 http://www.cnblogs.com/happyframework/p/3224278.html 背景 准备写个博客练习一下WEB编程,有一个需求就是多模板支持,类似博客园的自定义模板一样,在ASP.

原文 http://www.cnblogs.com/happyframework/p/3224278.html

背景

准备写个博客练习一下WEB编程,有一个需求就是多模板支持,类似博客园的自定义模板一样,在ASP.NET MVC中如何处理这个需求呢?

需求

描述

允许自定义模板,比如:传统模板、Metro模板等

模板结构

实现思路1

重写模板引擎的默认搜索路径

复制代码
 1         private void SetTemplate(string template)
 2         {
 3             var razorViewEngine = ViewEngines.Engines.First(x => x is RazorViewEngine) as RazorViewEngine;
 4 
 5             razorViewEngine.ViewLocationFormats = razorViewEngine.ViewLocationFormats.Select(x =>
 6             {
 7                 return x.Replace("~/Views", string.Format("~/Views/Front/Templates/{0}", template));
 8             }).ToArray();
 9             razorViewEngine.MasterLocationFormats = razorViewEngine.ViewLocationFormats.Select(x =>
10             {
11                 return x.Replace("~/Views", string.Format("~/Views/Front/Templates/{0}", template));
12             }).ToArray();
13             razorViewEngine.PartialViewLocationFormats = razorViewEngine.ViewLocationFormats.Select(x =>
14             {
15                 return x.Replace("~/Views", string.Format("~/Views/Front/Templates/{0}", template));
16             }).ToArray();
17         }
复制代码

分析

这回导致全局的修改,或者应该增加一个搜索路径(这里就不测试了),因为有些视图是不用多模板支持的,因此这种方式不太适合。

实现思路2

为VIewResult指定路径

1         public ActionResult Index(string template = "Classic")
2         {
3             return this.View("~/Views/Front/Templates/" + template + "/Home/Index.cshtml");
4         }

分析

这种非常灵活,符合需要,但是代码看起来不够漂亮,好在MVC非常灵活,可以用Filter机制帮我们处理。

实现思路3

Filter机制

复制代码
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 using System.Web.Mvc;
 7 using System.Threading;
 8 
 9 using Happy.Bootstrap;
10 
11 namespace Happy.Web.Mvc.Template
12 {
13     /// <summary>
14     /// 模板相关。
15     /// </summary>
16     public sealed class TemplateRelevantAttribute : ActionFilterAttribute
17     {
18         /// <inheritdoc />
19         public override void OnResultExecuting(ResultExecutingContext filterContext)
20         {
21             var viewResult = filterContext.Result as ViewResult;
22             if (viewResult != null)
23             {
24                 var currentUserTemplate = this.GetCurrentUserTemplate();
25                 var template = string.IsNullOrEmpty(currentUserTemplate) ? TemplateService.DefaultTemplateName : currentUserTemplate;
26                 var controller = filterContext.RequestContext.RouteData.Values["Controller"].ToString();
27                 var action = filterContext.RequestContext.RouteData.Values["Action"].ToString();
28 
29                 if (string.IsNullOrWhiteSpace(viewResult.ViewName))
30                 {
31                     viewResult.ViewName = string.Format(
32                         "~/Views/{0}/{1}/{2}/{3}.{4}",
33                         TemplateService.TemplateDirectoryName,
34                         template,
35                         controller,
36                         action,
37                         TemplateService.TemplateFileExtension);
38 
39                     return;
40                 }
41             }
42 
43             base.OnResultExecuting(filterContext);
44         }
45 
46         private string GetCurrentUserTemplate()
47         {
48             return TemplateService.Current.GetTemplate(Thread.CurrentPrincipal.Identity.Name);
49         }
50     }
51 }
复制代码
复制代码
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Text;
 5 using System.Threading.Tasks;
 6 
 7 using Happy.Infrastructure.ExtentionMethods;
 8 
 9 namespace Happy.Web.Mvc.Template
10 {
11     /// <summary>
12     /// 获取或访问<see cref="ITemplateService"/>实例的唯一入口。
13     /// </summary>
14     public static class TemplateService
15     {
16         private static readonly EmptyTemplateService _DefaultCommandService = new EmptyTemplateService();
17 
18         private static TemplateServiceProvider currentProvider = () => _DefaultCommandService;
19 
20         static TemplateService()
21         {
22             TemplateDirectoryName = "Templates";
23             DefaultTemplateName = "Default";
24             TemplateFileExtension = "cshtml";
25         }
26 
27         /// <summary>
28         /// 获取当前应用程序正在使用的模板服务。
29         /// </summary>
30         public static ITemplateService Current
31         {
32             get { return currentProvider(); }
33         }
34 
35         /// <summary>
36         /// 设置当前应用程序正在使用的模板服务提供者。
37         /// </summary>
38         public static void SetProvider(TemplateServiceProvider provider)
39         {
40             provider.MustNotNull("provider");
41 
42             currentProvider = provider;
43         }
44 
45         /// <summary>
46         /// 模板路径。
47         /// </summary>
48         public static string TemplateDirectoryName { get; set; }
49 
50         /// <summary>
51         /// 默认模板。
52         /// </summary>
53         public static string DefaultTemplateName { get; set; }
54 
55         /// <summary>
56         /// 默认模板。
57         /// </summary>
58         public static string TemplateFileExtension { get; set; }
59     }
60 }
复制代码

分析

采用FIlter这种AOP机制,让调用代码看起来非常漂亮,最终就采用这种方式。

测试

代码

复制代码
 1 using System;
 2 using System.Collections.Generic;
 3 using System.Linq;
 4 using System.Web;
 5 using System.Web.Mvc;
 6 
 7 using Happy.Web.Mvc.Template;
 8 
 9 namespace Happy.MvcExample.Controllers
10 {
11     [TemplateRelevant]
12     public class HomeController : Controller
13     {
14         //
15         // GET: /Home/
16 
17         public ActionResult Index()
18         {
19             return View();
20         }
21 
22         //
23         // GET: /Home/
24 
25         public ActionResult ChangeTemplate(string template)
26         {
27             TemplateService.DefaultTemplateName = template ?? TemplateService.DefaultTemplateName;
28 
29             return this.RedirectToAction("Index");
30         }
31     }
32 }
复制代码

运行效果

 

备注

ViewResult的ViewName可以是绝对路径,也可以是相对路径,默认的相对路径是相对于Controller目录。

目录
相关文章
|
3月前
|
开发框架 前端开发 .NET
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
ASP.NET CORE 3.1 MVC“指定的网络名不再可用\企图在不存在的网络连接上进行操作”的问题解决过程
41 0
|
1月前
|
开发框架 前端开发 .NET
进入ASP .net mvc的世界
进入ASP .net mvc的世界
29 0
|
1月前
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
|
4月前
|
开发框架 .NET
Asp.Net就业课堂之模板控件
Asp.Net就业课堂之模板控件
38 1
|
5月前
|
开发框架 自然语言处理 前端开发
基于ASP.NET MVC开发的、开源的个人博客系统
基于ASP.NET MVC开发的、开源的个人博客系统
52 0
|
8月前
|
存储 开发框架 前端开发
[回馈]ASP.NET Core MVC开发实战之商城系统(五)
经过一段时间的准备,新的一期【ASP.NET Core MVC开发实战之商城系统】已经开始,在之前的文章中,讲解了商城系统的整体功能设计,页面布局设计,环境搭建,系统配置,及首页【商品类型,banner条,友情链接,降价促销,新品爆款】,商品列表页面,商品详情等功能的开发,今天继续讲解购物车功能开发,仅供学习分享使用,如有不足之处,还请指正。
115 0
|
9月前
|
开发框架 前端开发 .NET
[回馈]ASP.NET Core MVC开发实战之商城系统(三)
[回馈]ASP.NET Core MVC开发实战之商城系统(三)
67 0

相关实验场景

更多