/ Controllers
/ Demo
/ Demo / DemoArea1Controller
/ Demo / DemoArea2Controller
等...
/视图
/ Demo
/ Demo / DemoArea1 / Index .aspx
/Demo/DemoArea2/Index.aspx
但是,当我在
DemoArea1Controller
上有此功能时:public class DemoArea1Controller : Controller
{
public ActionResult Index()
{
return View();
}
}
出现“找不到视图'索引'或它的主视图”错误,并带有通常的搜索位置。
如何在“演示”中指定控制器在“演示”视图子文件夹中进行名称空间搜索?
#1 楼
您可以轻松地扩展WebFormViewEngine来指定要查看的所有位置:public class CustomViewEngine : WebFormViewEngine
{
public CustomViewEngine()
{
var viewLocations = new[] {
"~/Views/{1}/{0}.aspx",
"~/Views/{1}/{0}.ascx",
"~/Views/Shared/{0}.aspx",
"~/Views/Shared/{0}.ascx",
"~/AnotherPath/Views/{0}.ascx"
// etc
};
this.PartialViewLocationFormats = viewLocations;
this.ViewLocationFormats = viewLocations;
}
}
请确保您记得通过修改自己的Application_Start方法来注册视图引擎。 Global.asax.cs
protected void Application_Start()
{
ViewEngines.Engines.Clear();
ViewEngines.Engines.Add(new CustomViewEngine());
}
评论
如何从嵌套母版页访问母版页的路径?与设置嵌套母版页布局一样,在CustomViewEngine的路径中进行搜索
–德拉希尔
2012-12-18 18:27
如果我们跳过“清除已注册的引擎”并仅添加新引擎,而viewLocations仅包含新引擎,这会更好吗?
– Prasanna
2014年9月1日上午11:43
没有ViewEngines.Engines.Clear()的实现;一切正常。如果要使用* .cshtml,则必须从RazorViewEngine继承
– KregHEk
15年2月19日在11:40
有什么方法可以将控制器的“添加视图”和“转到视图”选项链接到新视图位置?我正在使用Visual Studio 2012
– Neville Nazerane
16年11月19日,0:39
如@Prasanna所述,无需清除现有引擎即可添加新位置,有关更多详细信息,请参见此答案。
–霍曼·巴里尼(Hooman Bahreini)
1月26日4:28
#2 楼
现在,在MVC 6中,您可以实现IViewLocationExpander
接口,而不会弄乱视图引擎:public class MyViewLocationExpander : IViewLocationExpander
{
public void PopulateValues(ViewLocationExpanderContext context) {}
public IEnumerable<string> ExpandViewLocations(ViewLocationExpanderContext context, IEnumerable<string> viewLocations)
{
return new[]
{
"/AnotherPath/Views/{1}/{0}.cshtml",
"/AnotherPath/Views/Shared/{0}.cshtml"
}; // add `.Union(viewLocations)` to add default locations
}
}
其中
{0}
是目标视图名称,{1}
-控制器名称,{2}
-区域名称。 您可以返回自己的位置列表,将其与默认的
viewLocations
(.Union(viewLocations)
)合并,也可以仅更改它们(viewLocations.Select(path => "/AnotherPath" + path)
)。要在MVC中注册自定义视图位置扩展器,请在
ConfigureServices
文件中的Startup.cs
方法中添加下一行:public void ConfigureServices(IServiceCollection services)
{
services.Configure<RazorViewEngineOptions>(options =>
{
options.ViewLocationExpanders.Add(new MyViewLocationExpander());
});
}
评论
我希望我能以10票赞成。正是Asp.net 5 / MVC 6所需要的。漂亮。当您想将区域分为大型区域或逻辑分组的超级区域时,对我(或其他人)非常有用。
–机敏
2015年11月19日在7:08
Startup.cs部分应该是:services.Configure
– OrangeKing89
16-10-20在13:08
#3 楼
实际上,有比将路径硬编码到构造函数中更简单的方法。以下是扩展Razor引擎以添加新路径的示例。我不确定的一件事是,是否会缓存您在此处添加的路径:public class ExtendedRazorViewEngine : RazorViewEngine
{
public void AddViewLocationFormat(string paths)
{
List<string> existingPaths = new List<string>(ViewLocationFormats);
existingPaths.Add(paths);
ViewLocationFormats = existingPaths.ToArray();
}
public void AddPartialViewLocationFormat(string paths)
{
List<string> existingPaths = new List<string>(PartialViewLocationFormats);
existingPaths.Add(paths);
PartialViewLocationFormats = existingPaths.ToArray();
}
}
以及您的Global.asax.cs
protected void Application_Start()
{
ViewEngines.Engines.Clear();
ExtendedRazorViewEngine engine = new ExtendedRazorViewEngine();
engine.AddViewLocationFormat("~/MyThemes/{1}/{0}.cshtml");
engine.AddViewLocationFormat("~/MyThemes/{1}/{0}.vbhtml");
// Add a shared location too, as the lines above are controller specific
engine.AddPartialViewLocationFormat("~/MyThemes/{0}.cshtml");
engine.AddPartialViewLocationFormat("~/MyThemes/{0}.vbhtml");
ViewEngines.Engines.Add(engine);
AreaRegistration.RegisterAllAreas();
RegisterRoutes(RouteTable.Routes);
}
注意的一件事:您的自定义位置在其根目录中将需要ViewStart.cshtml文件。
#4 楼
如果只想添加新路径,则可以添加到默认视图引擎,并保留一些代码行:ViewEngines.Engines.Clear();
var razorEngine = new RazorViewEngine();
razorEngine.MasterLocationFormats = razorEngine.MasterLocationFormats
.Concat(new[] {
"~/custom/path/{0}.cshtml"
}).ToArray();
razorEngine.PartialViewLocationFormats = razorEngine.PartialViewLocationFormats
.Concat(new[] {
"~/custom/path/{1}/{0}.cshtml", // {1} = controller name
"~/custom/path/Shared/{0}.cshtml"
}).ToArray();
ViewEngines.Engines.Add(razorEngine);
WebFormEngine
也是如此
评论
对于视图:使用razorEngine.ViewLocationFormats。
– Aldentev
2015年10月21日在9:36
#5 楼
您可以仅更改现有RazorViewEngine的PartialViewLocationFormats属性,而不必继承RazorViewEngine的子类或直接替换它。该代码位于Application_Start中:System.Web.Mvc.RazorViewEngine rve = (RazorViewEngine)ViewEngines.Engines
.Where(e=>e.GetType()==typeof(RazorViewEngine))
.FirstOrDefault();
string[] additionalPartialViewLocations = new[] {
"~/Views/[YourCustomPathHere]"
};
if(rve!=null)
{
rve.PartialViewLocationFormats = rve.PartialViewLocationFormats
.Union( additionalPartialViewLocations )
.ToArray();
}
评论
这对我有用,但剃须刀引擎类型为“ FixedRazorViewEngine”而不是“ RazorViewEngine”。如果找不到引擎,我也会抛出一个异常,因为它阻止了我的应用程序成功初始化。
–Rob
16-4-5 6:00
#6 楼
最后我检查了一下,这需要您构建自己的ViewEngine。我不知道它们是否使RC1变得更容易。我在第一个RC之前使用的基本方法是在我自己的ViewEngine中,拆分控制器的名称空间并查找文件夹,匹配了零件。
编辑:
回去找到代码。这是一般的想法。
public override ViewEngineResult FindView(ControllerContext controllerContext, string viewName, string masterName)
{
string ns = controllerContext.Controller.GetType().Namespace;
string controller = controllerContext.Controller.GetType().Name.Replace("Controller", "");
//try to find the view
string rel = "~/Views/" +
(
ns == baseControllerNamespace ? "" :
ns.Substring(baseControllerNamespace.Length + 1).Replace(".", "/") + "/"
)
+ controller;
string[] pathsToSearch = new string[]{
rel+"/"+viewName+".aspx",
rel+"/"+viewName+".ascx"
};
string viewPath = null;
foreach (var path in pathsToSearch)
{
if (this.VirtualPathProvider.FileExists(path))
{
viewPath = path;
break;
}
}
if (viewPath != null)
{
string masterPath = null;
//try find the master
if (!string.IsNullOrEmpty(masterName))
{
string[] masterPathsToSearch = new string[]{
rel+"/"+masterName+".master",
"~/Views/"+ controller +"/"+ masterName+".master",
"~/Views/Shared/"+ masterName+".master"
};
foreach (var path in masterPathsToSearch)
{
if (this.VirtualPathProvider.FileExists(path))
{
masterPath = path;
break;
}
}
}
if (string.IsNullOrEmpty(masterName) || masterPath != null)
{
return new ViewEngineResult(
this.CreateView(controllerContext, viewPath, masterPath), this);
}
}
//try default implementation
var result = base.FindView(controllerContext, viewName, masterName);
if (result.View == null)
{
//add the location searched
return new ViewEngineResult(pathsToSearch);
}
return result;
}
评论
实际上,这要容易得多。子类化WebFormsViewEngine,然后将其添加到它已经在构造函数中搜索的路径数组。
– Craig Stuntz
09年3月11日在2:52
很高兴知道。我上一次需要修改该集合时,无法以这种方式进行。
–乔尔
2009年3月11日13:57
值得一提的是,您需要在基本控制器名称空间(例如“ Project.Controllers”)中设置“ baseControllerNamespace”变量,但在发布7年后,它确实满足了我的需要。
–prototype14
16-10-31在22:38
#7 楼
尝试这样的事情:private static void RegisterViewEngines(ICollection<IViewEngine> engines)
{
engines.Add(new WebFormViewEngine
{
MasterLocationFormats = new[] {"~/App/Views/Admin/{0}.master"},
PartialViewLocationFormats = new[] {"~/App/Views/Admin//{1}/{0}.ascx"},
ViewLocationFormats = new[] {"~/App/Views/Admin//{1}/{0}.aspx"}
});
}
protected void Application_Start()
{
RegisterViewEngines(ViewEngines.Engines);
}
#8 楼
注意:对于ASP.NET MVC 2,您需要为“区域”中的视图设置其他位置路径。 AreaViewLocationFormats
AreaPartialViewLocationFormats
AreaMasterLocationFormats
为Area创建视图引擎是
注意:这是针对预览版本1的,可能会有所更改。
#9 楼
此处的大多数答案都可以通过调用ViewEngines.Engines.Clear()
清除现有位置,然后再次将其重新添加...无需这样做。我们可以简单地将新位置添加到现有位置中,如下所示:
// note that the base class is RazorViewEngine, NOT WebFormViewEngine
public class ExpandedViewEngine : RazorViewEngine
{
public ExpandedViewEngine()
{
var customViewSubfolders = new[]
{
// {1} is conroller name, {0} is action name
"~/Areas/AreaName/Views/Subfolder1/{1}/{0}.cshtml",
"~/Areas/AreaName/Views/Subfolder1/Shared/{0}.cshtml"
};
var customPartialViewSubfolders = new[]
{
"~/Areas/MyAreaName/Views/Subfolder1/{1}/Partials/{0}.cshtml",
"~/Areas/MyAreaName/Views/Subfolder1/Shared/Partials/{0}.cshtml"
};
ViewLocationFormats = ViewLocationFormats.Union(customViewSubfolders).ToArray();
PartialViewLocationFormats = PartialViewLocationFormats.Union(customPartialViewSubfolders).ToArray();
// use the following if you want to extend the master locations
// MasterLocationFormats = MasterLocationFormats.Union(new[] { "new master location" }).ToArray();
}
}
现在,您可以将项目配置为在Global.asax中使用上述
RazorViewEngine
:protected void Application_Start()
{
ViewEngines.Engines.Add(new ExpandedViewEngine());
// more configurations
}
了解更多信息,请参见本教程。
#10 楼
我是在MVC 5中这样做的。我不想清除默认位置。帮助程序类:
namespace ConKit.Helpers
{
public static class AppStartHelper
{
public static void AddConKitViewLocations()
{
// get engine
RazorViewEngine engine = ViewEngines.Engines.OfType<RazorViewEngine>().FirstOrDefault();
if (engine == null)
{
return;
}
// extend view locations
engine.ViewLocationFormats =
engine.ViewLocationFormats.Concat(new string[] {
"~/Views/ConKit/{1}/{0}.cshtml",
"~/Views/ConKit/{0}.cshtml"
}).ToArray();
// extend partial view locations
engine.PartialViewLocationFormats =
engine.PartialViewLocationFormats.Concat(new string[] {
"~/Views/ConKit/{0}.cshtml"
}).ToArray();
}
}
}
然后在Application_Start中:
// Add ConKit View locations
ConKit.Helpers.AppStartHelper.AddConKitViewLocations();
评论
这是Rob Connery的MVC Commerce应用程序中另一个简单ViewView的示例:View Engine代码和用于设置ViewEngine的Global.asax.cs代码:Global.asax.cs希望这会有所帮助。