我的mvc项目有以下布局:
/控制器
/演示
/演示/ DemoArea1Controller
/演示/ DemoArea2Controller
等等...
/浏览次数
/演示
/Demo/DemoArea1/Index.aspx
/Demo/DemoArea2/Index.aspx
但是,当我有这个DemoArea1Controller
:
public class DemoArea1Controller : Controller { public ActionResult Index() { return View(); } }
我通过常用的搜索位置得到"视图'索引'或其主人找不到"错误.
如何在"Demo"视图子文件夹中指定"演示"命名空间中的控制器?
您可以轻松扩展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; } }
确保记住通过修改Global.asax.cs中的Application_Start方法来注册视图引擎
protected void Application_Start() { ViewEngines.Engines.Clear(); ViewEngines.Engines.Add(new CustomViewEngine()); }
现在在MVC 6中,您可以实现IViewLocationExpander
接口而不会弄乱视图引擎:
public class MyViewLocationExpander : IViewLocationExpander { public void PopulateValues(ViewLocationExpanderContext context) {} public IEnumerableExpandViewLocations(ViewLocationExpanderContext context, IEnumerable viewLocations) { return new[] { "/AnotherPath/Views/{1}/{0}.cshtml", "/AnotherPath/Views/Shared/{0}.cshtml" }; // add `.Union(viewLocations)` to add default locations } }
其中{0}
是目标视图名称,{1}
- 控制器名称和{2}
- 区域名称.
您可以返回自己的位置列表,将其与default viewLocations
(.Union(viewLocations)
)合并或只更改它们(viewLocations.Select(path => "/AnotherPath" + path)
).
要在MVC中注册自定义视图位置扩展器,请ConfigureServices
在Startup.cs
文件中的方法中添加下一行:
public void ConfigureServices(IServiceCollection services) { services.Configure(options => { options.ViewLocationExpanders.Add(new MyViewLocationExpander()); }); }
实际上,比将路径硬编码到构造函数中要容易得多.下面是扩展Razor引擎以添加新路径的示例.我不太确定的一件事是你在这里添加的路径是否会被缓存:
public class ExtendedRazorViewEngine : RazorViewEngine { public void AddViewLocationFormat(string paths) { ListexistingPaths = new List (ViewLocationFormats); existingPaths.Add(paths); ViewLocationFormats = existingPaths.ToArray(); } public void AddPartialViewLocationFormat(string paths) { List existingPaths = new List (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文件.
如果您只想添加新路径,可以添加到默认视图引擎并备用一些代码行:
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
您可以直接更改现有的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(); }