创建自定义路由约束 (C#)

作者 :Stephen Walther

Stephen Walther 演示了如何创建自定义路由约束。 我们实现了一个简单的自定义约束,该约束可防止在从远程计算机发出浏览器请求时匹配路由。

本教程的目的是演示如何创建自定义路由约束。 自定义路由约束使你能够阻止路由匹配,除非匹配某些自定义条件。

在本教程中,我们将创建一个 Localhost 路由约束。 Localhost 路由约束仅匹配从本地计算机发出的请求。 来自 Internet 的远程请求不匹配。

通过实现 IRouteConstraint 接口来实现自定义路由约束。 这是一个极其简单的接口,它描述了一个方法:

bool Match(
    HttpContextBase httpContext,
    Route route,
    string parameterName,
    RouteValueDictionary values,
    RouteDirection routeDirection
)

方法返回布尔值。 如果返回 false,则与约束关联的路由与浏览器请求不匹配。

Localhost 约束包含在清单 1 中。

清单 1 - LocalhostConstraint.cs

using System.Web;
using System.Web.Routing;
namespace MvcApplication1.Constraints
{
    public class LocalhostConstraint : IRouteConstraint
    {
        public bool Match
            (
                HttpContextBase httpContext, 
                Route route, 
                string parameterName, 
                RouteValueDictionary values, 
                RouteDirection routeDirection
            )
        {
            return httpContext.Request.IsLocal;
        }
    }
}

清单 1 中的约束利用 HttpRequest 类公开的 IsLocal 属性。 当请求的 IP 地址为 127.0.0.1 或请求的 IP 与服务器的 IP 地址相同时,此属性返回 true。

在 Global.asax 文件中定义的路由中使用自定义约束。 清单 2 中的 Global.asax 文件使用 Localhost 约束来阻止任何人请求管理员页面,除非他们从本地服务器发出请求。 例如,从远程服务器发出 /管理员/DeleteAll 的请求将失败。

清单 2 - Global.asax

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using MvcApplication1.Constraints;
namespace MvcApplication1
{
    public class MvcApplication : System.Web.HttpApplication
    {
        public static void RegisterRoutes(RouteCollection routes)
        {
            routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
            routes.MapRoute(
                "Admin",
                "Admin/{action}",
                new {controller="Admin"},
                new {isLocal=new LocalhostConstraint()}
            );
            //routes.MapRoute(
            //    "Default",                                              // Route name
            //    "{controller}/{action}/{id}",                           // URL with parameters
            //    new { controller = "Home", action = "Index", id = "" }  // Parameter defaults
            //);
        }
        protected void Application_Start()
        {
            RegisterRoutes(RouteTable.Routes);
        }
    }
}

Localhost 约束用于管理员路由的定义中。 远程浏览器请求不会匹配此路由。 但是,请注意,Global.asax 中定义的其他路由可能与同一请求匹配。 请务必了解,约束会阻止特定路由匹配请求,而不是与 Global.asax 文件中定义的所有路由匹配。

请注意,已从清单 2 中的 Global.asax 文件注释掉默认路由。 如果包含默认路由,则默认路由将匹配管理员控制器的请求。 在这种情况下,远程用户仍然可以调用管理员控制器的操作,即使他们的请求与管理员路由不匹配。