Background
ready to write a blog about WEB programming practice, there is a demand that is multi-template support, similar to blog park custom template, in ASP.NET MVC how to deal with this demand?
Requirements
Description
allow custom template, such as: the traditional template, Metro templates, etc.
template structure
realization of ideas 1
override the default template engine search path
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 }
analysis
this time lead to global changes, or should add a search path (not tested here), because some of the views are not multi-template support, so this approach is not suitable.
realization of ideas 2
as VIewResult specified path
1 public ActionResult Index(string template = "Classic")
2 {
3 return this.View("~/Views/Front/Templates/" + template + "/Home/Index.cshtml");
4 }
analysis
This very flexible and meet your needs, but the code looks pretty enough, but fortunately MVC is very flexible and can help us deal with the Filter mechanism.
realization of ideas 3
Filter mechanism
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 }
analysis
using FIlter this AOP mechanism to allow the calling code looks very nice, and ultimately on the use of this approach.
Test
code
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 }
operating results
Notes
ViewResult of ViewName can be an absolute path or a relative path, the default relative path is relative to the Controller directory.
finally make up code: http://yunpan.cn/QnYjcK3hTB3qk .
this was very useful thank u very much..
回复删除