Url.Action MVC3在构建链接时无法识别路由参数

时间:2012-08-14 16:11:18

标签: asp.net-mvc-3 asp.net-mvc-routing url.action

在我的路由参数中添加自定义路由约束时,我发现它破坏了我用来构建链接的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.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无法识别我的路径参数的任何想法?

1 个答案:

答案 0 :(得分: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帮助程序一起使用,则必须将其删除。