在利用ASP.NET MVC 框架编写程序时,有时我们需要根据业务自己选择视图模板存放的位置,比如针对用户的设置选择不同的皮肤。如下:
我们建一个 Themes/{Channel}/{Theme}/{Controller}/ {Action} 的存放路径,视图模板还用webform。 在Url客户端的显示上,我们还遵循{Channel}/{Controller}/ {Action}规则。
实现思路是重写实现写一个ThemeViewEngine, 实现IViewEngine,作用是选择正确的WebForumView 的路径。
看下实现代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Hosting;
namespace MvcApplicationTest.ThemeEngines
{
/// <summary>
/// 皮肤选择引擎
/// </summary>
public class ThemeViewEngine:IViewEngine
{
#region IViewEngine 成员
public ViewEngineResult FindView(ControllerContext controllerContext,
string viewName, string masterName, bool useCache)
{
return _FindView(controllerContext, viewName, null, useCache, "aspx");
}
public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
return _FindView(controllerContext, partialViewName, null, useCache, "ascx");
}
public void ReleaseView(ControllerContext controllerContext, IView view)
{
IDisposable disposable = view as IDisposable;
if (disposable != null)
disposable.Dispose();
}
#endregion
private ViewEngineResult _FindView(ControllerContext controllerContext,
string viewName, string masterName, bool useCache, string ext)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext is required.", "controllerContext");
if (string.IsNullOrEmpty(viewName))
throw new ArgumentException("viewName is required.", "viewName");
//当前不允许在Controller中指定View的masterName
if (!string.IsNullOrEmpty(masterName))
{
throw new ArgumentException("不允许在Controller中指定View的masterName", "masterName");
}
string selectedThemeName = GetSelectedTheme(controllerContext);
string controllerName = controllerContext.RouteData.Values["controller"].ToString();
string viewPath = GetViewPath(controllerContext, selectedThemeName, controllerName, viewName, ext);
if (viewPath == null)
throw new InvalidOperationException(String.Format("The view '{0}' could not be located at these paths: {1}",
viewName, GetChannelName(controllerContext)));
return new ViewEngineResult(new WebFormView(viewPath, null), this);
}
#region Help Methods
/// <summary>
/// 获取皮肤文件路径
/// </summary>
private static string GetViewPath(ControllerContext controllerContext,
string themeName, string controllerName, string viewName, string ext)
{
return String.Format(@"~/Themes/{0}/{1}/{2}/{3}.{4}", GetChannelName(controllerContext), themeName, controllerName, viewName, ext);
}
private static string GetChannelName(ControllerContext controllerContext)
{
if (controllerContext.RouteData.Values["channel"] == null)
{
return "";
}
else
{
return controllerContext.RouteData.Values["channel"].ToString();
}
}
/// <summary>
/// 获取需要显示的主题名称
/// </summary>
private static string GetSelectedTheme(ControllerContext controllerContext)
{
string themeName = "Default";
if (GetChannelName(controllerContext).ToLower() == "channel")
{
themeName = "Default";
}
return themeName;
}
#endregion
}
}
在应用时,还需配置Global
routes.MapRoute(
"Channel", // Route name
"{channel}/{controller}/{action}/{id}", // URL with parameters
new { channel="Channel", controller = "Home", action = "Index",
id = "" } // Parameter defaults
);
ViewEngines.Engines.Add(new ThemeEngines.ThemeViewEngine());