我可以指定一个自定义位置在ASP.NET MVC中“search视图”吗?

我有我的mvc项目的以下布局:

  • /控制器
    • /演示
    • /演示/ DemoArea1Controller
    • /演示/ DemoArea2Controller
    • 等等…
  • /浏览次数
    • /演示
    • /Demo/DemoArea1/Index.aspx
    • /Demo/DemoArea2/Index.aspx

但是,当我有这样的DemoArea1Controller

 public class DemoArea1Controller : Controller { public ActionResult Index() { return View(); } } 

我得到“查看”索引或其主人无法find“错误,与通常的search位置。

如何在“Demo”视图子文件夹的“Demo”命名空间search中指定该控制器?

您可以轻松地扩展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()); } 

实际上比将硬件path硬编码到构造函数中要简单得多。 以下是扩展Razor引擎以添加新path的示例。 我不完全确定的一件事是你在这里添加的path是否会被caching:

 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文件。

现在,在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中注册自定义视图位置扩展器,请将以下行添加到Startup.cs文件中的ConfigureServices方法:

 public void ConfigureServices(IServiceCollection services) { services.Configure<RazorViewEngineOptions>(options => { options.ViewLocationExpanders.Add(new MyViewLocationExpander()); }); } 

如果你只想添加新的path,你可以添加到默认的视图引擎和备用一些代码行:

 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属性,而不是直接replaceRazorViewEngine或直接replaceRazorViewEngine。 这段代码进入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(); } 

最后我检查了一下,这需要你build立你自己的ViewEngine。 但是我不知道他们是否让RC1更容易。

我在第一个RC之前使用的基本方法是,在我自己的ViewEngine中,分割控制器的名称空间,并查找与部分相匹配的文件夹。

编辑:

回去find了代码。 这是一般的想法。

 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; } 

尝试这样的事情:

 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); } 

注意:对于ASP.NET MVC 2,他们有额外的位置path,您需要在“区域”中设置视图。

  AreaViewLocationFormats AreaPartialViewLocationFormats AreaMasterLocationFormats 

Phil的博客描述了为Area创build视图引擎。

注:这是预览版本1,因此可能会有所变化。