原文 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. 在Raspberry上使用小度WIFI

    小度WIFI价格便宜量又足,我一真用它!做个广告先! 它使用联发科MT7601的芯片,质量不错,就是Raspberry下不能直接支持. 首先下载驱动 http://www.mediatek.com/_ ...

  2. 设置PlaceHolder的颜色

    input::-webkit-input-placeholder{ color:green; } input::-webkit-input-placeholder { color: #999; } i ...

  3. PASCAL的优越性:官方的说法(不需要Makefile,节约大量的时间)

    也许你认为为什么我选择pascal代替其他的语言,像C.或者您会拿FreePascal和其他的pascal编译器作比较,那么好,这里您看看FreePascal为什么好: 1.pascal是一个非常简洁 ...

  4. hibernate安装和配置和第一个Hibernate应用

    ssh的各个版本要搭配好,struts2.3一般搭配hibernate4.x,我下的是4.3. Hibernate4的改动较大只有spring3.1以上版本能够支持,Spring3.1取消了Hiber ...

  5. MFC radio button 绑定变量用法

    我们在对话框中拖动一个radio button控件,然后点击类向导,结果却发现在Member Variables里看不到Radio控件的ID.这是为什么? 2.1 三个Radio Button,ID分 ...

  6. android 控件的移动

    android 控件的移动 1. Java代码 imagebutton.setOnTouchListener(newOnTouchListener(){ int[]postion=newint[]{0 ...

  7. UESTC_邱老师选妹子(二) 2015 UESTC Training for Dynamic Programming<Problem I>

    I - 邱老师选妹子(二) Time Limit: 3000/1000MS (Java/Others)     Memory Limit: 65535/65535KB (Java/Others) Su ...

  8. N-Queens 解答

    Question The n-queens puzzle is the problem of placing n queens on an n×n chessboard such that no tw ...

  9. Implement Stack using Queues 解答

    Question Implement the following operations of a stack using queues. push(x) -- Push element x onto ...

  10. 分享几种Linux软件的安装方法

    Linux软件安装由于不同的Linux分支,安装方法也互不相同,介绍几种常见的安装方法. 1. 源码安装,     对于本身具有开源血统的Linux系统来说,几乎所有的开源软件都支持在Linux平台运 ...