如何在ASP.NET MVC中更改默认视图位置方案?
我想根据当前UI区域性在运行时更改视图位置。如何使用默认的Web表单视图引擎实现这一点 基本上,我想知道如何使用如何在ASP.NET MVC中更改默认视图位置方案?,.net,asp.net-mvc,viewengine,.net,Asp.net Mvc,Viewengine,我想根据当前UI区域性在运行时更改视图位置。如何使用默认的Web表单视图引擎实现这一点 基本上,我想知道如何使用WebFormViewEngine实现所包含的内容 是否有其他视图引擎可以让我在运行时控制视图位置 编辑:我的URL应该如下所示{lang}/{controller}/{action}/{id}。我不需要依赖于语言的控制器和视图,它们是使用资源本地化的。然而,在某些语言中,很少有不同的观点。因此,我需要告诉视图引擎首先查看特定于语言的文件夹。我认为解决方案是创建您自己的视图引擎,它继
WebFormViewEngine
实现所包含的内容
是否有其他视图引擎可以让我在运行时控制视图位置
编辑:我的URL应该如下所示
{lang}/{controller}/{action}/{id}
。我不需要依赖于语言的控制器和视图,它们是使用资源本地化的。然而,在某些语言中,很少有不同的观点。因此,我需要告诉视图引擎首先查看特定于语言的文件夹。我认为解决方案是创建您自己的视图引擎,它继承了WebFormViewEngine。在构造函数中,它应该从当前线程检查当前UI区域性,并添加适当的位置。只是别忘了将其添加到视图引擎中
这应该是这样的:
public class ViewEngine : WebFormViewEngine
{
public ViewEngine()
{
if (CultureIsX())
ViewLocationFormats = new string[]{"route1/controller.aspx"};
if (CultureIsY())
ViewLocationFormats = new string[]{"route2/controller.aspx"};
}
}
在global.asax中:
ViewEngines.Engines.Add(new ViewEngine());
必须更改VirtualPathProviderViewEngine.GetPathFromGeneralName以允许路由中的附加参数。它不是公共的,这就是为什么您必须将
GetPath
,GetPathFromGeneralName
,IsSpecificPath
…复制到您自己的ViewEngine
实现中
你说得对:这看起来像是一次彻底的重写。我希望GetPathFromGeneralName
是公共的
using System.Web.Mvc;
using System;
using System.Web.Hosting;
using System.Globalization;
using System.Linq;
namespace MvcLocalization
{
public class LocalizationWebFormViewEngine : WebFormViewEngine
{
private const string _cacheKeyFormat = ":ViewCacheEntry:{0}:{1}:{2}:{3}:";
private const string _cacheKeyPrefix_Master = "Master";
private const string _cacheKeyPrefix_Partial = "Partial";
private const string _cacheKeyPrefix_View = "View";
private static readonly string[] _emptyLocations = new string[0];
public LocalizationWebFormViewEngine()
{
base.ViewLocationFormats = new string[] {
"~/Views/{1}/{2}/{0}.aspx",
"~/Views/{1}/{2}/{0}.ascx",
"~/Views/Shared/{2}/{0}.aspx",
"~/Views/Shared/{2}/{0}.ascx" ,
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx"
};
}
private VirtualPathProvider _vpp;
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
if (controllerContext == null)
throw new ArgumentNullException("controllerContext");
if (String.IsNullOrEmpty(viewName))
throw new ArgumentException( "viewName");
string[] viewLocationsSearched;
string[] masterLocationsSearched;
string controllerName = controllerContext.RouteData.GetRequiredString("controller");
string viewPath = GetPath(controllerContext, ViewLocationFormats, "ViewLocationFormats", viewName, controllerName, _cacheKeyPrefix_View, useCache, out viewLocationsSearched);
string masterPath = GetPath(controllerContext, MasterLocationFormats, "MasterLocationFormats", masterName, controllerName, _cacheKeyPrefix_Master, useCache, out masterLocationsSearched);
if (String.IsNullOrEmpty(viewPath) || (String.IsNullOrEmpty(masterPath) && !String.IsNullOrEmpty(masterName)))
{
return new ViewEngineResult(viewLocationsSearched.Union(masterLocationsSearched));
}
return new ViewEngineResult(CreateView(controllerContext, viewPath, masterPath), this);
}
private string GetPath(ControllerContext controllerContext, string[] locations, string locationsPropertyName, string name, string controllerName, string cacheKeyPrefix, bool useCache, out string[] searchedLocations)
{
searchedLocations = _emptyLocations;
if (String.IsNullOrEmpty(name))
return String.Empty;
if (locations == null || locations.Length == 0)
throw new InvalidOperationException();
bool nameRepresentsPath = IsSpecificPath(name);
string cacheKey = CreateCacheKey(cacheKeyPrefix, name, (nameRepresentsPath) ? String.Empty : controllerName);
if (useCache)
{
string result = ViewLocationCache.GetViewLocation(controllerContext.HttpContext, cacheKey);
if (result != null)
{
return result;
}
}
return (nameRepresentsPath) ?
GetPathFromSpecificName(controllerContext, name, cacheKey, ref searchedLocations) :
GetPathFromGeneralName(controllerContext, locations, name, controllerName, cacheKey, ref searchedLocations);
}
private string GetPathFromGeneralName(ControllerContext controllerContext, string[] locations, string name, string controllerName, string cacheKey, ref string[] searchedLocations)
{
string result = String.Empty;
searchedLocations = new string[locations.Length];
string language = controllerContext.RouteData.Values["lang"].ToString();
for (int i = 0; i < locations.Length; i++)
{
string virtualPath = String.Format(CultureInfo.InvariantCulture, locations[i], name, controllerName,language);
if (FileExists(controllerContext, virtualPath))
{
searchedLocations = _emptyLocations;
result = virtualPath;
ViewLocationCache.InsertViewLocation(controllerContext.HttpContext, cacheKey, result);
break;
}
searchedLocations[i] = virtualPath;
}
return result;
}
private string CreateCacheKey(string prefix, string name, string controllerName)
{
return String.Format(CultureInfo.InvariantCulture, _cacheKeyFormat,
GetType().AssemblyQualifiedName, prefix, name, controllerName);
}
private string GetPathFromSpecificName(ControllerContext controllerContext, string name, string cacheKey, ref string[] searchedLocations)
{
string result = name;
if (!FileExists(controllerContext, name))
{
result = String.Empty;
searchedLocations = new[] { name };
}
ViewLocationCache.InsertViewLocation(controllerContext.HttpContext, cacheKey, result);
return result;
}
private static bool IsSpecificPath(string name)
{
char c = name[0];
return (c == '~' || c == '/');
}
}
}
使用System.Web.Mvc;
使用制度;
使用System.Web.Hosting;
利用制度全球化;
使用System.Linq;
命名空间MvcLocalization
{
公共类本地化WebFormViewEngine:WebFormViewEngine
{
私有常量字符串_cacheKeyFormat=“:ViewCacheEntry:{0}:{1}:{2}:{3}:”;
私有常量字符串\u cacheKeyPrefix\u Master=“Master”;
私有常量字符串\u cacheKeyPrefix\u Partial=“Partial”;
私有常量字符串\u cacheKeyPrefix\u View=“View”;
私有静态只读字符串[]_emptyLocations=新字符串[0];
公共本地化WebFormViewEngine()
{
base.ViewLocationFormats=新字符串[]{
“~/Views/{1}/{2}/{0}.aspx”,
“~/Views/{1}/{2}/{0}.ascx”,
“~/Views/Shared/{2}/{0}.aspx”,
“~/Views/Shared/{2}/{0}.ascx”,
“~/Views/{1}/{0}.aspx”,
“~/Views/{1}/{0}.ascx”,
“~/Views/Shared/{0}.aspx”,
“~/Views/Shared/{0}.ascx”
};
}
私有VirtualPathProvider_vpp;
public override ViewEngineResult FindView(ControllerContext ControllerContext、string viewName、string masterName、bool useCache)
{
如果(controllerContext==null)
抛出新ArgumentNullException(“controllerContext”);
if(String.IsNullOrEmpty(viewName))
抛出新ArgumentException(“viewName”);
字符串[]viewLocationsSearched;
字符串[]主位置搜索;
string controllerName=controllerContext.RoutedData.GetRequiredString(“控制器”);
字符串viewPath=GetPath(controllerContext、ViewLocationFormats、“ViewLocationFormats”、viewName、controllerName、_-cacheKeyPrefix_-View、useCache、out-viewLocationsSearched);
字符串masterPath=GetPath(controllerContext,MasterLocationFormats,“MasterLocationFormats”,masterName,controllerName,_cacheKeyPrefix_Master,useCache,out masterLocationsSearched);
if(String.IsNullOrEmpty(viewPath)| |(String.IsNullOrEmpty(masterPath)&&!String.IsNullOrEmpty(masterName)))
{
返回新的ViewEngineResult(viewLocationsSearched.Union(masterLocationsSearched));
}
返回新的ViewEngineResult(CreateView(controllerContext、viewPath、masterPath),此选项为;
}
私有字符串GetPath(ControllerContext ControllerContext,字符串[]位置,字符串位置PropertyName,字符串名称,字符串controllerName,字符串cacheKeyPrefix,bool useCache,out字符串[]搜索位置)
{
搜索位置=_清空位置;
if(String.IsNullOrEmpty(name))
返回字符串。空;
如果(位置==null | |位置。长度==0)
抛出新的InvalidOperationException();
bool nameRepresentsPath=IsSpecificPath(名称);
string cacheKey=CreateCacheKey(cacheKeyPrefix,名称,(nameRepresentsPath)?string.Empty:controllerName);
如果(使用缓存)
{
字符串结果=ViewLocationCache.GetViewLocation(controllerContext.HttpContext,cacheKey);
如果(结果!=null)
{
返回结果;
}
}
返回(名称代表SPATH)?
GetPathFromSpecificName(controllerContext、name、cacheKey、ref searchedLocations):
GetPathFromGeneralName(controllerContext、位置、名称、controllerName、cacheKey、ref searchedLocations);
}
私有字符串GetPathFromGeneralName(ControllerContext ControllerContext,string[]位置,string名称,string controllerName,string cacheKey,ref string[]searchedLocations)
{
字符串结果=string.Empty;
searchedLocations=新字符串[locations.Length];
string language=controllerContext.RouteData.Values[“lang”].ToString();
对于(int i=0;ipublic LocalizationWebFormViewEngine()
{
base.PartialViewLocationFormats = new string[] {
"~/Views/{2}/{1}/{0}.cshtml",
"~/Views/{2}/{1}/{0}.aspx",
"~/Views/{2}/Shared/{0}.cshtml",
"~/Views/{2}/Shared/{0}.aspx"
};
base.ViewLocationFormats = new string[] {
"~/Views/{2}/{1}/{0}.cshtml",
"~/Views/{2}/{1}/{0}.aspx",
"~/Views/{2}/Shared/{0}.cshtml",
"~/Views/{2}/Shared/{0}.aspx"
};
}
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, String partialViewName, Boolean useCache)
{
if (controllerContext == null)
{
throw new ArgumentNullException("controllerContext");
}
if (String.IsNullOrEmpty(partialViewName))
{
throw new ArgumentException("partialViewName");
}
string[] partialViewLocationsSearched;
string controllerName = controllerContext.RouteData.GetRequiredString("controller");
string partialPath = GetPath(controllerContext, PartialViewLocationFormats, "PartialViewLocationFormats", partialViewName, controllerName, _cacheKeyPrefix_Partial, useCache, out partialViewLocationsSearched);
return new ViewEngineResult(CreatePartialView(controllerContext, partialPath), this);}
}
public class LocalizedViewEngine : RazorViewEngine
{
private string[] _defaultViewLocationFormats;
public LocalizedViewEngine()
: base()
{
// Store the default locations which will be used to append
// the localized view locations based on the thread Culture
_defaultViewLocationFormats = base.ViewLocationFormats;
}
public override ViewEngineResult FindPartialView(ControllerContext controllerContext, string partialViewName, bool useCache)
{
AppendLocalizedLocations();
return base.FindPartialView(controllerContext, partialViewName, useCache:fase);
}
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName, bool useCache)
{
AppendLocalizedLocations();
returnbase.FindView(controllerContext, viewName, masterName, useCache:false);
}
private void AppendLocalizedLocations()
{
// Use language two letter name to identify the localized view
string lang = Thread.CurrentThread.CurrentUICulture.TwoLetterISOLanguageName;
// Localized views will be in the format "{action}.{lang}.cshtml"
string localizedExtension = string.Format(".{0}.cshtml", lang);
// Create an entry for views and layouts using localized extension
string view = "~/Views/{1}/{0}.cshtml".Replace(".cshtml", localizedExtension);
string shared = "~/Views/{1}/Shared/{0}".Replace(".cshtml", localizedExtension);
// Create a copy of the default view locations to modify
var list = _defaultViewLocationFormats.ToList();
// Insert the new locations at the top of the list of locations
// so they're used before non-localized views.
list.Insert(0, shared);
list.Insert(0, view);
base.ViewLocationFormats = list.ToArray();
}
}
protected void Application_Start()
{
...
// Allow looking up views in ~/Features/ directory
var razorEngine = ViewEngines.Engines.OfType<RazorViewEngine>().First();
razorEngine.ViewLocationFormats = razorEngine.ViewLocationFormats.Concat(new string[]
{
"~/Features/{1}/{0}.cshtml"
}).ToArray();
...
// also: razorEngine.PartialViewLocationFormats if required
}
ViewLocationFormats = new string[]
{
"~/Views/{1}/{0}.cshtml",
"~/Views/{1}/{0}.vbhtml",
"~/Views/Shared/{0}.cshtml",
"~/Views/Shared/{0}.vbhtml"
};