当前位置 > 首页 > Asp.net

扩展URL Routing:处理URL中的日期参数

2009-6-5 16:06:00来源:Asp.net

对URL中的日期参数,老赵提供了一个非常经典的解决方案。但是这里的日期参数是以yyyy-MM-dd的形式出现的,用户往往会有这样的需求,即URL中的参数一定要为Demo/Date/2009/06/05的形式。由于RouteData是以/来划分segment的,老赵的方案似乎就不适用了。

国外的大牛们大多推崇将日期分隔为年、月、日,通过扩展IRouteConstraint来对年月日分别进行判断。引用老赵的话来说,“无论从易用性还是通用性等角度来看,这种做法都是下下之策。说实话,这样的做法其实并没有跳出框架既有功能给定的圈子,它只是通过“迎合框架”来满足自己的需求,而不是让框架为我们的需求服务。”

其实要实现这样的需求也不难,只需要对老赵的方案稍微修改一下就可以了。我们将URL定义为Demo/Date/{year}/{month}/{day},然后在生成RouteData时,将year、month、day组合成date;生成路径时,再将date划分为year、month、day。

新建一个DateFormatRoute类,让它继承自RouteBase。在GetRouteData方法中拼接年月日,其余方法与老赵的相同。

public override RouteData GetRouteData(HttpContextBase httpContext)
{
    var routeData = route.GetRouteData(httpContext);
    if (routeData.Values["year"] != null)
    {
        string date = routeData.Values["year"].ToString() + routeData.Values["month"].ToString() + routeData.Values["day"].ToString();
        routeData.Values.Remove("year");
        routeData.Values.Remove("month");
        routeData.Values.Remove("day");
        routeData.Values["date"] = date;
    }
    else
    {
        return null;
    }

    var valuesModified = new Dictionary<string, object>();
    foreach (var pair in routeData.Values)
    {
        var key = pair.Key;
        IRouteFormatter formatter = null;
        if (this.formatters.TryGetValue(key, out formatter))
        { 
            object o;
            if (formatter.TryParse(pair.Value, out o))
            {
                valuesModified[key] = o;
            }
            else
            {
                return null;
            }
        }
    }

    foreach (var pair in valuesModified)
    {
        routeData.Values[pair.Key] = pair.Value;
    }
    return routeData;
}

在GetVirtualPath方法中,再将年月日分解到各个segment中。

public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
{
    var routeValues = new RouteValueDictionary();
    foreach (