代码之家  ›  专栏  ›  技术社区  ›  jessegavin

在尝试创建友好和“可破解”的URL时,使用url.action()时遇到问题

  •  1
  • jessegavin  · 技术社区  · 14 年前

    我为一个简单的博客定义了以下路径。

    routes.MapRoute(
      "Blog",
      "blog/{year}/{month}/{day}",
      new { controller = "Blog", action = "Index" },
      new { year = @"\d{4}", month = @"\d{2}", day = @"\d{2}" }
    );
    

    该网址应能“黑客”完成以下工作:

    我已经创建了一个控制器,可以很好地处理这个操作。但是,我在使用 Url.Action()

    例如…

    var d = new DateTime(2010, 1, 25);
    Url.Action("Index", "Blog", new { year=d.Year, month=d.Month, day=d.Day} );
    

    …生成如下所示的URL:

    http://abc.com/blog?year=2010&month=2&day=21

    我希望它生成一个类似于上面列表中的url的url。

    http://abc.com/blog/2010/02/21

    我能用什么方法 Actuple() Html.ActionLink() 以我想要的格式生成url?

    3 回复  |  直到 14 年前
        1
  •  3
  •   Eilon    14 年前

    问题是你要去的那个月 Url.Action 是一个位数的月份,因此与路由定义上的月份约束不匹配。约束通常不仅在传入的url上运行,而且在生成url时也会运行。

    修复方法是在月份手动调用.tostring(),并将其格式化为两位数。你今天也需要这样做。对于这一年来说,这不是一个问题,因为我们一生中的所有年份都是四位数。

    下面是格式化数字的示例代码:

    int month = 2;
    string formattedMonth = month.ToString("00", CultureInfo.InvariantCulture);
    // formattedMonth == "02"
    

    请注意,手动格式化数字时,必须使用固定区域性,以便不同的区域性和语言不会影响其格式化方式。

    您还需要设置月和日的默认值,以便在URL中不需要它们:

    routes.MapRoute( 
      "Blog", 
      "blog/{year}/{month}/{day}", 
      new { controller = "Blog", action = "Index", month = "00", day = "00" }, 
      new { year = @"\d{4}", month = @"\d{2}", day = @"\d{2}" } 
    );
    

    在控制器操作中,检查月或日是否为0,在这种情况下,应该显示整个月或全年。

        2
  •  0
  •   DM.    14 年前

    我看到您遇到的另一个问题是,您将需要其他几个具有适当默认值的路由条目来处理这些其他场景。

    http://abc.com/2010 “将不匹配”blog/{year}/{month}/{day}“。这是一个非常具体的路由,需要三个参数(带约束)来匹配。为了接受这些其他路由,您需要沿以下行创建其他路由条目:

    routes.MapRoute(
      null,
      "blog",
      new { controller = "Blog", action = "Index", year = 0000, month = 00, day = 00 },
      new { year = @"\d{4}", month = @"\d{2}", day = @"\d{2}" }
    );
    
    routes.MapRoute(
      null,
      "blog/{year}",
      new { controller = "Blog", action = "Index", month = 00, day = 00 },
      new { year = @"\d{4}" }
    );
    
    routes.MapRoute(
      null,
      "blog/{year}/{month}",
      new { controller = "Blog", action = "Index", day = 00 },
      new { year = @"\d{4}", month = @"\d{2}"}
    );
    

    有几种方法可以处理这个场景,但是现在在blog控制器和索引操作中,您可以按年、月、日筛选文章结果。

    快速示例:

    if(year == 0000 && month == 00 && day == 00)
        var posts = postsRepository.GetAllPost();
    else if(year != 0000 && month == 00 && day == 00)
        var posts = postsRepository.GetPostsByYear(year);
    

        3
  •  0
  •   cem    14 年前

    你不必为所有情况编写新方法。我是说你可以用这个来做;

    例如,对尼伯纳特。

    public IList<Blog> GetBlogs(int? day, int? month, int? year) {
        IQueryable<Blog> iQBlog = Session.Linq<Blog>();
    
        if (year.HasValue) {
            iQBlog = iQBlog.Where(b => b.Year == year);
    
            if (month.HasValue) {
                iQBlog = iQBlog.Where(b => b.Month == month);
    
                if (day.HasValue) {
                    iQBlog = iQBlog.Where(b => b.Day == day);
                }
            }
        }
    
        return iQBlog.ToList();
    }
    

    另外,它正在逐步检查参数,年->月->日。如果用户没有在querystring中设置任何参数,它将返回所有博客。