ASP.NET MVC:多模板支持
原文 http://www.cnblogs.com/happyframework/p/3224278.html
背景
准备写个博客练习一下WEB编程,有一个需求就是多模板支持,类似博客园的自定义模板一样,在ASP.NET MVC中如何处理这个需求呢?
需求
描述
允许自定义模板,比如:传统模板、Metro模板等
模板结构
实现思路1
重写模板引擎的默认搜索路径

private void SetTemplate(string template)
{
var razorViewEngine = ViewEngines.Engines.First(x => x is RazorViewEngine) as RazorViewEngine; razorViewEngine.ViewLocationFormats = razorViewEngine.ViewLocationFormats.Select(x =>
{
return x.Replace("~/Views", string.Format("~/Views/Front/Templates/{0}", template));
}).ToArray();
razorViewEngine.MasterLocationFormats = razorViewEngine.ViewLocationFormats.Select(x =>
{
return x.Replace("~/Views", string.Format("~/Views/Front/Templates/{0}", template));
}).ToArray();
razorViewEngine.PartialViewLocationFormats = razorViewEngine.ViewLocationFormats.Select(x =>
{
return x.Replace("~/Views", string.Format("~/Views/Front/Templates/{0}", template));
}).ToArray();
}

分析
这回导致全局的修改,或者应该增加一个搜索路径(这里就不测试了),因为有些视图是不用多模板支持的,因此这种方式不太适合。
实现思路2
为VIewResult指定路径
public ActionResult Index(string template = "Classic")
{
return this.View("~/Views/Front/Templates/" + template + "/Home/Index.cshtml");
}
分析
这种非常灵活,符合需要,但是代码看起来不够漂亮,好在MVC非常灵活,可以用Filter机制帮我们处理。
实现思路3
Filter机制

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Threading; using Happy.Bootstrap; namespace Happy.Web.Mvc.Template
{
/// <summary>
/// 模板相关。
/// </summary>
public sealed class TemplateRelevantAttribute : ActionFilterAttribute
{
/// <inheritdoc />
public override void OnResultExecuting(ResultExecutingContext filterContext)
{
var viewResult = filterContext.Result as ViewResult;
if (viewResult != null)
{
var currentUserTemplate = this.GetCurrentUserTemplate();
var template = string.IsNullOrEmpty(currentUserTemplate) ? TemplateService.DefaultTemplateName : currentUserTemplate;
var controller = filterContext.RequestContext.RouteData.Values["Controller"].ToString();
var action = filterContext.RequestContext.RouteData.Values["Action"].ToString(); if (string.IsNullOrWhiteSpace(viewResult.ViewName))
{
viewResult.ViewName = string.Format(
"~/Views/{0}/{1}/{2}/{3}.{4}",
TemplateService.TemplateDirectoryName,
template,
controller,
action,
TemplateService.TemplateFileExtension); return;
}
} base.OnResultExecuting(filterContext);
} private string GetCurrentUserTemplate()
{
return TemplateService.Current.GetTemplate(Thread.CurrentPrincipal.Identity.Name);
}
}
}


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks; using Happy.Infrastructure.ExtentionMethods; namespace Happy.Web.Mvc.Template
{
/// <summary>
/// 获取或访问<see cref="ITemplateService"/>实例的唯一入口。
/// </summary>
public static class TemplateService
{
private static readonly EmptyTemplateService _DefaultCommandService = new EmptyTemplateService(); private static TemplateServiceProvider currentProvider = () => _DefaultCommandService; static TemplateService()
{
TemplateDirectoryName = "Templates";
DefaultTemplateName = "Default";
TemplateFileExtension = "cshtml";
} /// <summary>
/// 获取当前应用程序正在使用的模板服务。
/// </summary>
public static ITemplateService Current
{
get { return currentProvider(); }
} /// <summary>
/// 设置当前应用程序正在使用的模板服务提供者。
/// </summary>
public static void SetProvider(TemplateServiceProvider provider)
{
provider.MustNotNull("provider"); currentProvider = provider;
} /// <summary>
/// 模板路径。
/// </summary>
public static string TemplateDirectoryName { get; set; } /// <summary>
/// 默认模板。
/// </summary>
public static string DefaultTemplateName { get; set; } /// <summary>
/// 默认模板。
/// </summary>
public static string TemplateFileExtension { get; set; }
}
}

分析
采用FIlter这种AOP机制,让调用代码看起来非常漂亮,最终就采用这种方式。
测试
代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc; using Happy.Web.Mvc.Template; namespace Happy.MvcExample.Controllers
{
[TemplateRelevant]
public class HomeController : Controller
{
//
// GET: /Home/ public ActionResult Index()
{
return View();
} //
// GET: /Home/ public ActionResult ChangeTemplate(string template)
{
TemplateService.DefaultTemplateName = template ?? TemplateService.DefaultTemplateName; return this.RedirectToAction("Index");
}
}
}

运行效果
备注
ViewResult的ViewName可以是绝对路径,也可以是相对路径,默认的相对路径是相对于Controller目录。
ASP.NET MVC:多模板支持的更多相关文章
- Asp.net MVC Razor模板引擎技巧分享
Razor是Asp.net MVC中新的默认模板类型, 语法简单易用.这篇文章不涉及Razor的语法,主要介绍Razor的一些在MVC项目中的使用技巧,以及脱离MVC环境下,如何使用Razor. 阅读 ...
- MVC多模板支持
参考: ASP.NET MVC:多模板支持
- SimpleMembership,成员资格提供程序、 通用的提供者和新的 ASP.NET 4.5 Web 窗体和 ASP.NET MVC 4 模板
ASP.NET MVC 4 互联网模板中添加一些新的. 非常有用的功能,构建 SimpleMembership.这些更改将添加一些很有特色,像很多更简单. 可扩展会员 API 和 OAuth 的支持. ...
- ASP.NET MVC 解析模板生成静态页一(RazorEngine)
简述 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项.在早期的MVC版本中默认使用的是ASPX模板引擎,Razor在语法上的确不错,用起来非常方便,简洁的语法 ...
- ASP.NET MVC]WebAPI应用支持HTTPS的经验总结
WebAPI应用支持HTTPS的经验总结 在我前面介绍的WebAPI文章里面,介绍了WebAPI的架构设计方面的内容,其中提出了现在流行的WebAPI优先的路线,这种也是我们开发多应用(APP.微信. ...
- ASP.NET MVC Bootstrap模板选中菜单高亮显示当前项方法
当我们处理后台显示当前页面,当前页菜单项高亮,我们可以使用js方法,也可用程序实现,使用Bootstrap模板处理高亮并展开方法之一 1.在项目中导入 <script src="/as ...
- ASP.NET MVC使用Bootstrap系统(2)——使用Bootstrap CSS和HTML元素
阅读目录 Bootstrap 栅格(Grid)系统 Bootstrap HTML元素 Bootstrap 验证样式 ASP.NET MVC创建包含Bootstrap样式编辑模板 小结 Bootstra ...
- 转:在ASP.NET MVC中通过URL路由实现对多语言的支持
对于一个需要支持多语言的Web应用,一个很常见的使用方式就是通过请求地址来控制界面呈现所基于的语言文化,比如我们在表示请求地址的URL中将上语言文化代码(比如en或者en-US)来指导服务器应该采用怎 ...
- ASP.NET MVC 5 默认模板的JS和CSS 是怎么加载的?
当创建一个默认的mvc模板后,项目如下: 运行项目后,鼠标右键查看源码,在源码里看到头部和尾部都有js和css文件被引用,他们是怎么被添加进来的呢? 首先我们先看对应的view文件index.csht ...
- ASP.Net MVC 5 in Xamarin Studio 5.2
Xamarin Studio 是一个Mono的跨平台 IDE(Integrated Development Environment),支持Wiindow和Mac,最新发布的5.2 版本支持ASP.NE ...
随机推荐
- js 图片无缝循环
<html> <head> <title>Js图片无缝滚动</title> <style type="text/css"> ...
- 简单的QT绘图程序(把全部的点都记录下来,然后在paintEvent里使用drawLine函数进行绘制,貌似效率很低。。。)
当初在学MFC时,最经典的入门实例就是绘图程序,其作用相当于Console Application 下的Hello World了吧. 如今入手QT,不免怀旧,于是也写了一个绘图程序,虽然简单,却也是入 ...
- javascript之数组
一.定义数组. 定义数组有两个方法: 1.var arr1 = []; //定义一个空数组 2.var arr2 = [1,2,3,"str1","str2"] ...
- selenium webdriver使用过程中出现Element is not currently visible and so may not be interacted with的处理方法
参考文章: http://blog.csdn.net/passionboyxie/article/details/28661107 http://www.spasvo.com/ceshi/open/k ...
- C语言的本质(37)——makefile之隐含规则和模式规则
Makefile有很多灵活的写法,可以写得更简洁,同时减少出错的可能.本节我们来看看这样一个例子还有哪些改进的余地. 一个目标依赖的所有条件不一定非得写在一条规则中,也可以拆开写,例如: main.o ...
- codecomb 2090【最小乘积路】
题目描述 给定n个点的带权有向图,求从1到n的路径中边权之积最小的简单路径. 输入格式 第一行读入两个整数n,m,表示共n个点m条边. 接下来m行,每行三个正整数x,y,z,表示点x到点y有一条边权为 ...
- 用日志文件备份sqlserver
USE [TestDB] GO SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO )) as ) ),),)),)+ '.bak' backup dat ...
- Jquery时间验证和转换工具
var TimeObjectUtil; /** * @title 时间工具类 * @note 本类一律违规验证返回false * @author {boonyachengdu@gmail.com} * ...
- UESTC_方老师买表 CDOJ 885
老师买表 Time Limit: 3000/1000MS (Java/Others) Memory Limit: 65535/65535KB (Java/Others) Submit Stat ...
- hdu 5630 Rikka with Chess
来自官方题解: AC代码: #pragma comment(linker, "/STACK:1024000000,1024000000") #include<iostream ...