ASP.NET MVC:多模板支持

背景

準備寫個博客練習一下WEB編程,有一個需求就是多模板支持,相似博客園的自定義模板同樣,在ASP.NET MVC中如何處理這個需求呢?html

需求

描述編程

容許自定義模板,好比:傳統模板、Metro模板等app

模板結構ide

實現思路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         }

分析this

這回致使全局的修改,或者應該增長一個搜索路徑(這裏就不測試了),由於有些視圖是不用多模板支持的,所以這種方式不太適合。spa

實現思路2

爲VIewResult指定路徑code

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

分析orm

這種很是靈活,符合須要,可是代碼看起來不夠漂亮,好在MVC很是靈活,能夠用Filter機制幫咱們處理。htm

實現思路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目錄。

最後補上代碼:http://yunpan.cn/QnYjcK3hTB3qk

相關文章
相關標籤/搜索