Asp.Net MVC:基于cookie的用户自选视图引擎实现


本文示例源代码或素材下载

  在我以前的文章中详细介绍了目前mvc框架中的视图引擎管理,这个视图引擎可以方便的实现系统多视图引擎的管理,让系统可以轻松更好视图引擎,但是,在一些应用,比如bbs,多用户blog中,往往需要提供用户自选skin的功能,比如bbs中某个用户通过菜单可以随意更换自己的skin设置,而mvc框架的默认视图管理器对这个要求就无法做到了,而本文则是使用viewengine规则来实现一个用户自选视图引擎的功能.

  在本系统中,用户选择的skin信息将保存在cookie中,这意味着可以让用户控制这个选择保存的时间.

  首先,这个系统仍然是基于ViewEngine,我们在以前的文章中可以看到,mvc框架用一个AutoViewEngine来管理存在的所有ViewEngine,那么我们也可以考虑用一个SelectViewEngine来管理一系列我们特定的可选择ViewEngine.下面先看看这个核心部分的类:

  从图中可以看到,这儿我们提供了一个新的接口ISelectViewEngine,它在普通的ViewEngine上添加了一个新的Name属性,该属性标示着唯一的视图引擎名称,然后我们对WebFormViewEngine进行封装,并实现ISelectViewEngine接口:

  Code

    public SelectWebFormViewEngine(string name) {
      Name = name;
      MasterLocationFormats = new[] {
        "~/skins/" + Name + "/{1}/{0}.master",
        "~/skins/" + Name + "/shared/{0}.master"
      };
      ViewLocationFormats = new[] {
        "~/skins/" + Name + "/{1}/{0}.aspx",
        "~/skins/" + Name + "/{1}/{0}.ascx",
        "~/skins/" + Name + "/shared/{0}.aspx",
        "~/skins/" + Name + "/shared/{0}.ascx"
      };
      PartialViewLocationFormats = ViewLocationFormats;
    }

从上面的代码可以看到,默认的不同skin分别放在~/skins目录下,不同的SelectWebFormViewEngine对应不同的子目录.

  然后我们实现一个基本的SelectViewEngine来管理所有的可选择ViewEngine,关键代码如下:

  Code

    /// <summary>
    /// 可选择视图引擎容器,通过Add来增加系统中可用的视图引擎
     /// </summary>
    public IDictionary<string, ISelectViewEngine> Engines {
      get { return _engines; }
    }
  
    /// <summary>
    /// 通过Cookie来选择用户所选择的ViewEngine
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    private IViewEngine Find(ControllerContext context) {
      string skin = context.HttpContext.GetSelectSkinName();
      if (!_engines.ContainsKey(skin)) {
        throw new Exception(String.Format("模板{0}未找到.", skin));
      }
      return _engines[skin];
    }
  
    #region IViewEngine Members
  
    /// <summary>
    /// 调用通过Find方法找到的ViewEngine的FindPartialView方法
    /// </summary>
    /// <param name="controllerContext"></param>
    /// <param name="partialViewName"></param>
    /// <returns></returns>
    public ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName) {
      return Find(controllerContext).FindPartialView(controllerContext, partialViewName);
    }
  
    /// <summary>
    /// 调用通过Find方法找到的ViewEngine的FindView方法
    /// </summary>
    /// <param name="controllerContext"></param>
    /// <param name="viewName"></param>
    /// <param name="masterName"></param>
    /// <returns></returns>
    public ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName) {
      return Find(controllerContext).FindView(controllerContext, viewName, masterName);
    }

那么我们如何确定用户选择了哪个ViewEngine呢?在本例中是采用了cookie的方式,在ViewEngineExtension中,我们封装了几个扩展方法用来获取cookie和设置cookie:

  Code

  public static class ViewEngineExtension {
    private static readonly string _cookiename = "select_skin_name";
    private static readonly string _defaultskin = "default";
  
    public static string GetSelectSkinName(this HttpContextBase context) {
      HttpCookie cookie = context.Request.Cookies[_cookiename];
      if (cookie != null) {
        return cookie.Value;
      }
      return _defaultskin;
    }
  
    public static void SelectSkin(this HttpContextBase context, ISelectViewEngine select) {
      HttpCookie cookie = new HttpCookie(_cookiename);
      cookie.Value = select.Name;
      if (context.Response.Cookies.AllKeys.Contains(_cookiename))
        context.Response.Cookies.Remove(_cookiename);
      context.Response.Cookies.Add(cookie);
    }
  
    public static void SelectSkin(this HttpContextBase context, string name) {
      HttpCookie cookie = new HttpCookie(_cookiename);
      cookie.Value = name;
      if (context.Response.Cookies.AllKeys.Contains(_cookiename))
        context.Response.Cookies.Remove(_cookiename);
      context.Response.Cookies.Add(cookie);
    }
  
    public static void ResetSkin(this HttpContextBase context) {
      HttpCookie cookie = new HttpCookie(_cookiename);
      cookie.Value = _defaultskin;
      if (context.Response.Cookies.AllKeys.Contains(_cookiename))
        context.Response.Cookies.Remove(_cookiename);
      context.Response.Cookies.Add(cookie);
    }
  }


  总结下VIewEngine的工作流程:

  Controller -> ViewEngines.Default.FindView -> SelectViewEngine.FindView -> SelectWebFormViewEngine.FindView

  也就是说,系统调用FindView或者FindPartialView方法最终还是会调用到我们在系统中已经注册过的ISelectViewEngine的FindView或者FindPartialView方法.最后展示下如何注册这些SelectViewEngine:

  Code

    protected void Application_Start(object sender, EventArgs e) {
    //注册路由
       InitRouting(RouteTable.Routes);
      ViewEngines.Engines.Clear();
      SelectViewEngine engine = new SelectViewEngine();
      SelectWebFormViewEngine defaultEngine = new SelectWebFormViewEngine();
      engine.Engines.Add(defaultEngine.Name, defaultEngine);
      SelectWebFormViewEngine selectEngine = new SelectWebFormViewEngine("select");
      engine.Engines.Add(selectEngine.Name, selectEngine);
      ViewEngines.Engines.Add(engine);
    }

  到此,所有功能实现…


« 
» 
快速导航

Copyright © 2016 phpStudy | 豫ICP备2021030365号-3