能否在不借助控制器的情况下直接将路由映射至视图?
解决重复空控制器操作的方案
方案1:统一基础控制器+自定义路由映射
先定义路由与视图路径的对照表,可做成配置类或静态字典:
Public Class ViewRouteMapping Public Shared ReadOnly Mappings As New Dictionary(Of String, String) From { {"home/details/{id}", "Home/Details"}, {"product/list", "Product/List"}, {"user/profile/{id}", "User/Profile"} ' 按需添加所有需要映射的路由与视图关系 } End Class
创建统一控制器处理这类仅返回视图的请求:
Public Class FallbackController Inherits Controller Public Function Index() As ActionResult ' 从路由数据中获取预定义的视图路径 Dim viewPath = RouteData.Values("viewPath").ToString() Return View(viewPath) End Function End Class
在路由配置中注册映射规则:
Public Class RouteConfig Public Shared Sub RegisterRoutes(routes As RouteCollection) routes.IgnoreRoute("{resource}.axd/{*pathInfo}") ' 先注册自定义映射路由 For Each mapping In ViewRouteMapping.Mappings routes.MapRoute( name:=mapping.Key.Replace("/", "_"), url:=mapping.Key, defaults:=New With {.controller = "Fallback", .action = "Index", .viewPath = mapping.Value} ) Next ' 常规默认路由 routes.MapRoute( name:="Default", url:="{controller}/{action}/{id}", defaults:=New With {.controller = "Home", .action = "Index", .id = UrlParameter.Optional} ) End Sub End Class
方案2:自定义RouteBase直接解析视图路径
若不想依赖统一控制器,可自定义RouteBase实现路由匹配,再通过HttpContext渲染视图:
自定义路由类:
Public Class ViewRoute Inherits RouteBase Private ReadOnly _mappings As Dictionary(Of String, String) Public Sub New(mappings As Dictionary(Of String, String)) _mappings = mappings End Sub Public Overrides Function GetRouteData(httpContext As HttpContextBase) As RouteData Dim requestUrl = httpContext.Request.AppRelativeCurrentExecutionFilePath.TrimStart("~/") ' 遍历对照表匹配路由 For Each mapping In _mappings Dim regexPattern = "^" + Regex.Replace(mapping.Key, "{[a-zA-Z0-9]+}", "([^/]+)") + "$" If Regex.IsMatch(requestUrl, regexPattern) Then Dim routeData = New RouteData(Me, New MvcRouteHandler()) routeData.Values("viewPath") = mapping.Value ' 提取路由参数(如id)存入路由数据 Dim matches = Regex.Match(requestUrl, regexPattern) Dim paramNames = Regex.Matches(mapping.Key, "{([a-zA-Z0-9]+)}").Cast(Of Match)().Select(Function(m) m.Groups(1).Value) For i = 0 To paramNames.Count - 1 routeData.Values(paramNames(i)) = matches.Groups(i + 1).Value Next Return routeData End If Next Return Nothing End Function Public Overrides Function GetVirtualPath(requestContext As RequestContext, values As RouteValueDictionary) As VirtualPathData ' 按需实现反向路由生成,此处暂返回Nothing Return Nothing End Function End Class
注册自定义路由:
Public Class RouteConfig Public Shared Sub RegisterRoutes(routes As RouteCollection) routes.IgnoreRoute("{resource}.axd/{*pathInfo}") ' 注册自定义视图路由 routes.Add(New ViewRoute(ViewRouteMapping.Mappings)) ' 常规默认路由 routes.MapRoute( name:="Default", url:="{controller}/{action}/{id}", defaults:=New With {.controller = "Home", .action = "Index", .id = UrlParameter.Optional} ) End Sub End Class
若要直接通过HttpContext返回视图,可实现IHttpHandler处理请求:
Public Class ViewHandler Implements IHttpHandler Public ReadOnly Property IsReusable As Boolean Implements IHttpHandler.IsReusable Get Return False End Get End Property Public Sub ProcessRequest(context As HttpContext) Implements IHttpHandler.ProcessRequest Dim requestUrl = context.Request.AppRelativeCurrentExecutionFilePath.TrimStart("~/") Dim viewPath = ViewRouteMapping.Mappings.FirstOrDefault(Function(m) Return Regex.IsMatch(requestUrl, "^" + Regex.Replace(m.Key, "{[a-zA-Z0-9]+}", "([^/]+)") + "$") End Function).Value If Not String.IsNullOrEmpty(viewPath) Then ' 查找视图并渲染 Dim controllerContext = New ControllerContext(context, New RouteData(), New Controller()) Dim viewResult = ViewEngines.Engines.FindView(controllerContext, viewPath, Nothing) If viewResult.View IsNot Nothing Then Dim viewContext = New ViewContext(controllerContext, viewResult.View, New ViewDataDictionary(), New TempDataDictionary(), context.Response.Output) viewResult.View.Render(viewContext, context.Response.Output) context.Response.End() End If End If ' 无匹配时交给默认MVC处理程序 HttpContext.Current.RemapHandler(MvcHttpHandler.DefaultHttpHandler) End Sub End Class
核心要点
- 本质是通过路由-视图路径映射表替代重复的空控制器操作,减少冗余代码。
- 直接用HttpContext返回视图时,需借助ASP.NET MVC的
ViewEngine查找视图,手动构建ViewContext完成渲染。 - 路由参数可通过正则提取后存入路由数据,视图中可通过
ViewContext.RouteData.Values获取使用。
内容的提问来源于stack exchange,提问作者Joshua Frank
相关产品推荐
相关产品推荐

