2

在向我的路由参数添加自定义路由约束时,我发现它破坏了我用来构建链接的 Url.Action 方法。如果路由约束只是一个正则表达式,那么 Url.Action 方法将继续识别参数,但是如果它是我定义的自定义约束,则 Url.Action 方法将我的参数作为请求参数。

这是我的路线定义:

routes.MapRoute(
            "Event",
            "Events/{strDate}",
            new { controller = "Events", action = "Index", strDate = DateTime.Today.ToString("yyyy-MM-dd") },
            new { strDate = new IsValidDateConstraint() },
            new[] { "MyProject.Controllers" }
        );

routes.MapRoute(
            "Default",
            "{controller}/{action}/{id}",
            new { controller = "Home", action = "Index", id = UrlParameter.Optional },
            new[] { "MyProject.Controllers" }
        );

IsValidDateConstraint 类继承自 IRouteConstraint,如果 strDate 参数正确解析为 DateTime 对象,则返回 true 或 false:

public class IsValidDateConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        if (routeDirection == RouteDirection.IncomingRequest)
        {
            DateTime dt = new DateTime();

            if (DateTime.TryParse(values["strDate"].ToString(), out dt))
                return true;
        }

        return false;
    }
}

使用 Url.Action 方法构建 URL:

@Url.Action("Index", "Events", new { strDate = ViewBag.CurrentDate.AddDays(1).ToString("yyyy-MM-dd") })

结果链接是:/Events?strDate=2012-08-15

如果我输入 /Events/2012-08-15,一切都会正确路由,只是 Url.Action 方法没有识别 strDate 是我的路由中定义的参数,只有当我应用我的自定义路由约束时。如果我注释掉自定义路由约束,那么 Url.Action 方法会正确映射 URL。

当我定义了自定义路由约束时,关于为什么 Url.Action 无法识别我的路由参数的任何想法?

4

1 回答 1

4

您尚未展示您的IsValidDateConstraint外观,但请确保您正在对yyyy-MM-dd格式进行文化不变的解析:

public class IsValidDateConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
    {
        DateTime date;
        return DateTime.TryParseExact(
            values[parameterName] as string, 
            "yyyy-MM-dd", 
            CultureInfo.InvariantCulture, 
            DateTimeStyles.None, 
            out date
        );
    }
}

还要确保将此路由放置在默认路由之前:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Event",
        "Events/{strDate}",
        new { controller = "Events", action = "Index", strDate = DateTime.Today.ToString("yyyy-MM-dd") },
        new { strDate = new IsValidDateConstraint() },
        new[] { "MyProject.Controllers" }
    );

    routes.MapRoute(
        "Default",
        "{controller}/{action}/{id}",
        new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

DateTime.Parse(ViewBag.CurrentDate.ToString())看起来有点 WTFkish 代码。如果ViewBag.CurrentDate已经是 DateTime 你可以直接写:

@Url.Action(
    "Index", 
    "Events", 
    new { 
        strDate = ViewBag.CurrentDate.AddDays(1).ToString("yyyy-MM-dd") 
    }
)

显然更好的解决方案是使用视图模型:

@Url.Action(
    "Index", 
    "Events", 
    new { 
        strDate = Model.CurrentDate.AddDays(1).ToString("yyyy-MM-dd") 
    }
)

更新:

现在您已经显示了代码,问题来自您在约束中设置的 if 条件:

if (routeDirection == RouteDirection.IncomingRequest)

当使用Url.Action助手时,这个条件永远不会满足。仅在解析传入 url 时。因此,如果您希望此约束与 url 帮助程序一起使用,则必须将其删除。

于 2012-08-14T16:21:04.997 回答