ASP.NET MVC:多模板支持

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

背景

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

需求

描述

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

模板结构

ASP.NET MVC:多模板支持

实现思路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 }
复制代码

运行效果

 ASP.NET MVC:多模板支持

ASP.NET MVC:多模板支持

备注

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

你可能感兴趣的:(asp.net)