zoukankan      html  css  js  c++  java
  • ASP.NET MVC:多模板支持

    背景

    准备写个博客练习一下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目录。

    最后补上代码:http://yunpan.cn/QnYjcK3hTB3qk

  • 相关阅读:
    "用脑思考"和"用心感知"
    Oracle 分页查询
    MySQL定时执行存储过程
    java商城小程序收藏
    巴士团小程序
    微信小程序this作用域
    Flink之API的使用(3):Source的使用
    Flink之API的使用(2):Transform算子的使用
    Flink之API的使用(1):Sink的使用
    Flink之基础内容(2):DataStream的创建和使用
  • 原文地址:https://www.cnblogs.com/happyframework/p/3224278.html
Copyright © 2011-2022 走看看