MVC应用启动时如何根据数据库返回值加载非默认自定义视图
解决方案
方案1:改造Home/Index动作(最优,无额外性能损耗)
你遇到的初始加载不触发Index方法的问题,大概率是浏览器缓存了之前的首页响应,或者Index动作配置了输出缓存未清理。首先给Index动作加上禁用缓存的标记,直接在动作内判断返回对应视图即可:
[OutputCache(NoStore = true, Duration = 0, VaryByParam = "*")] public ActionResult Index() { string targetView = CarnetsMVC.Classes.Utilities.GetView; // 匹配数据库存储的视图标识,返回对应视图 if(!string.IsNullOrEmpty(targetView)) { // 视图放在Views/Home目录下可直接传名称,其他路径需要写全路径,比如"~/Views/Shift/NightA.cshtml" return View(targetView); } // 默认返回原首页 return View(); }
确认你的默认路由配置未被修改,默认规则如下即可保证根路径请求必然触发Home/Index:
routes.MapRoute( name: "Default", url: "{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional } );
改完清理浏览器缓存后,首次打开应用就会直接返回匹配规则的视图,不需要在_layout中做任何判断。
方案2:全局动作过滤器兜底(适配特殊路由场景)
如果你的项目有特殊路由规则必须保留,可通过全局动作过滤器在请求到达控制器前就完成视图判断:
- 新建过滤器类
public class ViewSelectFilter : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext filterContext) { // 只处理根路径GET请求,避免拦截其他业务请求 if (filterContext.HttpContext.Request.Url.AbsolutePath == "/" && filterContext.HttpContext.Request.HttpMethod == "GET") { string targetView = CarnetsMVC.Classes.Utilities.GetView; if (!string.IsNullOrEmpty(targetView)) { filterContext.Result = new ViewResult { ViewName = targetView // 如需传递模型可在此处赋值ViewData/Model }; } } base.OnActionExecuting(filterContext); } }
- 在FilterConfig中注册全局过滤器
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); filters.Add(new ViewSelectFilter()); } }
该方案优先级最高,无论路由如何配置,只要是访问应用根路径的请求都会先经过过滤器判断,直接返回目标视图。
问题修复提示
注意:你当前的
Utilities.WhatView方法存在语法错误,try块中拿到视图名称后没有return语句,会导致编译报错,需要修正:public static string WhatView() { try { return (new DALUsers()).GetView().Tables[0].Rows[0]["view"].ToString(); } catch { return ""; } }
旧方案失效原因
- 判断逻辑放在_layout属于视图渲染阶段,此时MVC框架已经确定了要加载Home/Index视图,再做跳转/修改必然会有闪屏
- jQuery逻辑是客户端页面加载完成后才执行,必然会先展示默认首页再切换,达不到预期效果
- 单纯修改路由配置无法实现动态根据数据库结果返回视图的需求
内容的提问来源于stack exchange,提问作者CJR
相关产品推荐
相关产品推荐

