ASP.NET MVC 5如何从视图子文件夹中加载视图?
ASP.NET MVC加载多层子文件夹视图的解决方案
这不全是路由问题,但需要配合调整路由逻辑;必须自定义RazorViewEngine才能搞定多层子文件夹视图的加载——默认MVC的视图搜索规则不支持这种场景,而路由的默认解析逻辑也没法把多层路径映射成视图路径的一部分。
一、自定义视图引擎扩展搜索路径
默认的RazorViewEngine只会搜索~/Views/{controller}/{action}.cshtml这类固定结构的文件,要让它支持任意层级的子文件夹,直接扩展它的搜索格式即可:
public class CustomRazorViewEngine : RazorViewEngine { public CustomRazorViewEngine() { // 添加支持多层子路径的搜索规则 var extraViewPaths = new[] { "~/Views/{controller}/{*path}/{action}.cshtml", "~/Views/Shared/{*path}/{action}.cshtml" }; // 合并原有规则,保证默认视图的优先级不变 ViewLocationFormats = ViewLocationFormats.Union(extraViewPaths).ToArray(); PartialViewLocationFormats = PartialViewLocationFormats.Union(extraViewPaths).ToArray(); } }
然后在Application_Start里替换掉默认的视图引擎:
protected void Application_Start() { // 移除默认的Razor引擎 var defaultEngine = ViewEngines.Engines.OfType<RazorViewEngine>().First(); ViewEngines.Engines.Remove(defaultEngine); // 注册自定义视图引擎 ViewEngines.Engines.Add(new CustomRazorViewEngine()); // 其他初始化代码保持不变 AreaRegistration.RegisterAllAreas(); RouteConfig.RegisterRoutes(RouteTable.Routes); }
二、调整路由或改进HandleUnknownAction
仅修改视图引擎还不够,默认路由会把Student/About/Index里的About识别为actionName、Index识别为参数,无法正确映射到视图路径。这里提供两种解决方案:
方案1:修改路由捕获完整路径
在RouteConfig中添加专门针对Student和Employee控制器的路由,捕获控制器后的完整路径:
public class RouteConfig { public static void RegisterRoutes(RouteCollection routes) { routes.IgnoreRoute("{resource}.axd/{*pathInfo}"); // 优先处理Student/Employee的多层路径请求 routes.MapRoute( name: "CmsViews", url: "{controller}/{*viewPath}", defaults: new { action = "LoadCmsView" }, constraints: new { controller = "^(Student|Employee)$" } ); // 保留默认路由 routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } ); } }
然后在Student和Employee控制器中添加LoadCmsView方法,解析路径并加载视图:
public ActionResult LoadCmsView(string viewPath) { // 空路径默认返回Index视图 if (string.IsNullOrWhiteSpace(viewPath)) return View("Index"); // 直接用捕获到的完整路径查找视图 var viewResult = View(viewPath); // 视图不存在则返回404页面 if (!viewResult.ViewExists) return View("PageNotFound"); return viewResult; }
方案2:改进HandleUnknownAction解析请求路径
如果不想修改路由,可直接重写控制器的HandleUnknownAction方法,从请求URL中提取完整视图路径:
protected override void HandleUnknownAction(string actionName) { // 移除控制器路径部分,获取剩余的视图路径 var viewPath = Request.Url.AbsolutePath.Replace($"/{ControllerContext.RouteData.Values["controller"]}/", ""); // 尝试加载视图 var viewResult = View(viewPath); if (viewResult.ViewExists) { viewResult.ExecuteResult(ControllerContext); return; } // 视图不存在时返回404页面 View("PageNotFound").ExecuteResult(ControllerContext); }
三、验证效果
现在无论是Student/About/Index还是Student/About/Subfolder1/Subfolder2/Applying这类多层路径,自定义视图引擎都能精准定位对应的.cshtml文件;视图不存在时会自动跳转到PageNotFound页面,完全符合ASP.NET MVC的设计逻辑,无需手动处理文件存在性判断。
内容的提问来源于stack exchange,提问作者shanderson
相关产品推荐
相关产品推荐

