2011-05-12 100 views
3

我正在寻找自定义viewengine为asp.net mvc最简单的解决方案。所以我可以在路上寻找意见。自定义ViewEngine ASP.NET MVC 3

其实我试图在我的解决方案中构建一个主题系统。我浏览网页,但发现很难学习和实施的解决方案。

谢谢

回答

6

这就是我使用的。它在主题文件夹中查找视图。在构造函数的第一行设置主题名称。它还支持移动视图,但您需要51 Degrees Mobi之类的东西来为您提供移动浏览器详细信息。

using System; 
using System.Collections.Generic; 
using System.Web; 
using System.Web.Mvc; 

namespace Milkshake.Commerce.MvcClient.ViewEngines 
{ 
    /// <summary> 
    /// Milkshake Commerce specific ViewEngine. 
    /// </summary> 
    public class MilkshakeViewEngine : WebFormViewEngine 
    { 
     /// <summary> 
     /// Initializes a new instance of the <see cref="MilkshakeViewEngine"/> class. 
     /// </summary> 
     public MilkshakeViewEngine() 
     { 
      string themeName = AppData.ThemeName; 

      var masterLocationFormats = new List<string>(); 
      masterLocationFormats.Add("~/Views/Themes/" + themeName + "/{0}.master"); 
      masterLocationFormats.AddRange(MasterLocationFormats); 

      MasterLocationFormats = masterLocationFormats.ToArray(); 

      var partialViewLocationFormats = new List<string>(); 
      partialViewLocationFormats.Add("~/Views/Themes/" + themeName + "/{1}/{0}.aspx"); 
      partialViewLocationFormats.Add("~/Views/Themes/" + themeName + "/{1}/{0}.ascx"); 
      partialViewLocationFormats.Add("~/Views/Themes/" + themeName + "/{0}.aspx"); 
      partialViewLocationFormats.Add("~/Views/Themes/" + themeName + "/{0}.ascx"); 
      partialViewLocationFormats.AddRange(PartialViewLocationFormats); 

      PartialViewLocationFormats = partialViewLocationFormats.ToArray(); 

      var viewLocationFormats = new List<string>(); 
      viewLocationFormats.Add("~/Views/Themes/" + themeName + "/{1}/{0}.aspx"); 
      viewLocationFormats.Add("~/Views/Themes/" + themeName + "/{1}/{0}.ascx"); 
      viewLocationFormats.Add("~/Views/Themes/" + themeName + "/{0}.aspx"); 
      viewLocationFormats.Add("~/Views/Themes/" + themeName + "/{0}.ascx"); 
      viewLocationFormats.AddRange(ViewLocationFormats); 

      ViewLocationFormats = viewLocationFormats.ToArray(); 
     } 

     /// <summary> 
     /// Gets the user-selected <see cref="UserExperiences"/> setting, or returns the defualt if no experience has been selected. 
     /// </summary> 
     /// <returns>Returns the user experience selected by the user.</returns> 
     public static UserExperiences GetUserExperienceSelected() 
     { 
      HttpContext context = HttpContext.Current; 
      UserExperiences userExperience = context.Request.Browser.IsMobileDevice ? UserExperiences.Mobile : UserExperiences.Desktop; 
      var userExperienceCookie = context.Request.Cookies["UserExperience"]; 

      if (userExperienceCookie != null) 
      { 
       if (!String.IsNullOrWhiteSpace(userExperienceCookie.Value)) 
       { 
        Enum.TryParse<UserExperiences>(userExperienceCookie.Value, out userExperience); 
       } 
      } 
      else 
      { 
       SetUserExperience(userExperience); 
      } 

      return userExperience; 
     } 

     /// <summary> 
     /// Sets the user experience cookie. 
     /// </summary> 
     /// <param name="experience">The user experience.</param> 
     public static void SetUserExperience(UserExperiences experience) 
     { 
      HttpContext context = HttpContext.Current; 
      HttpCookie userExperienceCookie = context.Request.Cookies["UserExperience"]; 

      if (userExperienceCookie == null) 
      { 
       userExperienceCookie = new HttpCookie("UserExperience"); 
      } 

      userExperienceCookie.Value = experience.ToString(); 
      userExperienceCookie.Path = "/"; 
      userExperienceCookie.Expires = DateTime.UtcNow.AddDays(30); 

      context.Response.Cookies.Add(userExperienceCookie); 
     } 

     /// <summary> 
     /// Finds the specified view by using the specified controller context and master view name. 
     /// </summary> 
     /// <remarks>This override is used to determine if the browser is a mobile phone. 
     /// If so, and it is supported, we add the phone specific folder/view name to the existing viewname, 
     /// which forces the ViewManager to find a Theme specific mobile view (specific for that phone), or just use the built in mobile view.</remarks> 
     /// <param name="controllerContext">The controller context.</param> 
     /// <param name="viewName">The name of the view.</param> 
     /// <param name="masterName">The name of the master view.</param> 
     /// <param name="useCache">true to use the cached view.</param> 
     /// <returns>The page view.</returns> 
     /// <exception cref="T:System.ArgumentNullException">The <paramref name="controllerContext"/> parameter is null (Nothing in Visual Basic).</exception> 
     /// <exception cref="T:System.ArgumentException">The <paramref name="viewName"/> parameter is null or empty.</exception> 
     public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache) 
     { 
      ViewEngineResult result = null; 
      var request = controllerContext.HttpContext.Request; 
      var userExperience = GetUserExperienceSelected(); 

      // Avoid unnecessary checks if this device isn't suspected to be a mobile device 
      if (userExperience == UserExperiences.Mobile) 
      { 
       masterName = "Mobile/Mobile"; 
       result = base.FindView(controllerContext, "Mobile/" + viewName, masterName, useCache); 
      } 

      // Fall back to desktop view if no other view has been selected 
      if (result == null || result.View == null) 
      { 
       result = base.FindView(controllerContext, viewName, masterName, useCache); 
      } 

      return result; 
     } 

     /// <summary> 
     /// Adds the default mobile location formats. 
     /// </summary> 
     /// <param name="defaultLocationFormats">The default location formats.</param> 
     /// <param name="viewLocationFormats">The view location formats.</param> 
     private void AddDefaultMobileLocationFormats(string[] defaultLocationFormats, List<string> viewLocationFormats) 
     { 
      var mobileViewLocationFormats = new List<string>(); 

      foreach (var item in defaultLocationFormats) 
      { 
       if (item.Contains("Views/{1}/{0}")) 
       { 
        mobileViewLocationFormats.Add(item.Replace("/{1}/{0}", "/{1}/Mobile/{0}")); 
       } 
       else if (item.Contains("Views/Shared/{0}")) 
       { 
        mobileViewLocationFormats.Add(item.Replace("/Shared/{0}", "/Shared/Mobile/{0}")); 
       } 
      } 

      viewLocationFormats.AddRange(mobileViewLocationFormats); 
     } 
    } 
}