準備寫個博客練習一下WEB編程,有一個需求就是多模板支持,相似博客園的自定義模板同樣,在ASP.NET MVC中如何處理這個需求呢?html
描述編程
容許自定義模板,好比:傳統模板、Metro模板等app
模板結構ide
重寫模板引擎的默認搜索路徑測試
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
爲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
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。