You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

能否在不借助控制器的情况下直接将路由映射至视图?

解决重复空控制器操作的方案

方案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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 06:05:18