原文 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:多模板支持的更多相关文章

  1. Asp.net MVC Razor模板引擎技巧分享

    Razor是Asp.net MVC中新的默认模板类型, 语法简单易用.这篇文章不涉及Razor的语法,主要介绍Razor的一些在MVC项目中的使用技巧,以及脱离MVC环境下,如何使用Razor. 阅读 ...

  2. MVC多模板支持

    参考: ASP.NET MVC:多模板支持

  3. SimpleMembership,成员资格提供程序、 通用的提供者和新的 ASP.NET 4.5 Web 窗体和 ASP.NET MVC 4 模板

    ASP.NET MVC 4 互联网模板中添加一些新的. 非常有用的功能,构建 SimpleMembership.这些更改将添加一些很有特色,像很多更简单. 可扩展会员 API 和 OAuth 的支持. ...

  4. ASP.NET MVC 解析模板生成静态页一(RazorEngine)

    简述 Razor是ASP.NET MVC 3中新加入的技术,以作为ASPX引擎的一个新的替代项.在早期的MVC版本中默认使用的是ASPX模板引擎,Razor在语法上的确不错,用起来非常方便,简洁的语法 ...

  5. ASP.NET MVC]WebAPI应用支持HTTPS的经验总结

    WebAPI应用支持HTTPS的经验总结 在我前面介绍的WebAPI文章里面,介绍了WebAPI的架构设计方面的内容,其中提出了现在流行的WebAPI优先的路线,这种也是我们开发多应用(APP.微信. ...

  6. ASP.NET MVC Bootstrap模板选中菜单高亮显示当前项方法

    当我们处理后台显示当前页面,当前页菜单项高亮,我们可以使用js方法,也可用程序实现,使用Bootstrap模板处理高亮并展开方法之一 1.在项目中导入 <script src="/as ...

  7. ASP.NET MVC使用Bootstrap系统(2)——使用Bootstrap CSS和HTML元素

    阅读目录 Bootstrap 栅格(Grid)系统 Bootstrap HTML元素 Bootstrap 验证样式 ASP.NET MVC创建包含Bootstrap样式编辑模板 小结 Bootstra ...

  8. 转:在ASP.NET MVC中通过URL路由实现对多语言的支持

    对于一个需要支持多语言的Web应用,一个很常见的使用方式就是通过请求地址来控制界面呈现所基于的语言文化,比如我们在表示请求地址的URL中将上语言文化代码(比如en或者en-US)来指导服务器应该采用怎 ...

  9. ASP.NET MVC 5 默认模板的JS和CSS 是怎么加载的?

    当创建一个默认的mvc模板后,项目如下: 运行项目后,鼠标右键查看源码,在源码里看到头部和尾部都有js和css文件被引用,他们是怎么被添加进来的呢? 首先我们先看对应的view文件index.csht ...

  10. ASP.Net MVC 5 in Xamarin Studio 5.2

    Xamarin Studio 是一个Mono的跨平台 IDE(Integrated Development Environment),支持Wiindow和Mac,最新发布的5.2 版本支持ASP.NE ...

随机推荐

  1. "windows 正在启动"

    xp 在cmd下使用了control userpasswords2 设定开机不需要密码之后,开机停留在“window正在启动”,无法进入.估计是设置的时候密码输入错误了( 并不会提示你错误:() 在停 ...

  2. github orgmode

    http://blog.nicky1605.com/application-github-page.html http://dayigu.github.io/WhyUseOrgModeToWriteB ...

  3. 推荐大家一本学习php模式的书

    对我来讲,写程序不是码代码,不想只是简单的将类拿来调用,然后功能实现了,可是以后要做一些扩展或者是修改就要对代码大刀阔斧. 在网站的开发过程中,使用一些框架,团队就可以在一定的程度上,分工合作.但是当 ...

  4. 使用Qt编写服务器端程序(包括Http传输服务器端)的方法

    使用Qt编写客户端的程序的示例或demo较多,但是编写服务器端程序的demo很少.当然,服务器端的程序一般不需要带界面,这点我们可以理解.不过有些时候我们还是需要使用Qt编写一个简单的测试用的服务器代 ...

  5. EasyUI的下拉选择框控件方法被屏蔽处理方式

    1.html标签如下 <div id="selectMap" style="top: 1px;left: 80px;position: absolute;" ...

  6. hdu 4649 Professor Tian 多校联合训练的题

    这题起初没读懂题意,悲剧啊,然后看了题解写完就AC了 题意是给一个N,然后给N+1个整数 接着给N个操作符(只有三种操作  即  或 ,与 ,和异或 |   &  ^ )这样依次把操作符插入整 ...

  7. svn之——linux下清除svn的用户名和密码

    问题:之前用的svn账号权限不够,需要使用别的账号,所以提出需求——怎么使用新的svn账号进行操作 方法一: linux下删除~/.subversion/auth即可清除之前的用户名和密码:rm -r ...

  8. Hibernate绑定参数

    使用绑定参数的优势: 我们为什么要使用绑定命名参数?任何一个事物的存在都是有其价值的,具体到绑定参数对于HQL查询来说,主要有以下两个主要优势:①. 可以利用数据库实施性能优化 因为对Hibernat ...

  9. Web安全技术(3)-浏览器的跨域访问

    http://www.blogjava.net/linli/archive/2015/04/22/424584.html 一.浏览器介绍 对于Web应用来说,浏览器是最重要的客户端. 目前浏览器五花八 ...

  10. HDU 5740 - Glorious Brilliance

    题意: 给出已0 1染色的无向图(不一定联通),一次操作为一对相邻点颜色互换. 问使任意相邻点颜色不同,最少需要多少次操作 分析: 交换两点的代价即为两点间最短路. 故用BFS找出所有点到任意点的最短 ...