尝试创建友好的 & 时使用 Url.Action() 时遇到问题“可破解的”网址

发布于 2024-08-22 20:00:27 字数 1370 浏览 13 评论 0原文

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

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& ;月=2&日=21

我更希望它生成一个看起来像上面列表中的 url 的 url。

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

有吗我可以使用 Url.Action()Html.ActionLink() 来生成我想要的格式的网址吗?

I've defined the following route for a simple blog.

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

The url should be able "hackable" to accomplish the following:

I have created a controller which handles this action quite nicely. However I am having trouble creating links in my views using Url.Action().

For example this...

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

...generates a url like that looks like this:

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

I would rather like it to generate a url that looks like the urls in the list above.

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

Is there any way I can use Url.Action() or Html.ActionLink() to generate urls in the format I desire?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

财迷小姐 2024-08-29 20:00:27

问题在于您传递给 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,在这种情况下,您应该显示整个月份或全年。

The issue there is that the month you're passing in to Url.Action is a single-digit month, and thus doesn't match the month constraint on the route definition. Constraints are typically run not only on incoming URLs but also when generating URLs.

The fix would be to manually call .ToString() on the month and format it as a two-digit number. You'll need to do the same for the day as well. For the year it's not an issue since all the years in our lifetimes will be four-digit numbers.

Here's sample code to format numbers:

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

Please note that when formatting the number manually that you must use the Invariant Culture so that different cultures and languages won't affect how it gets formatted.

You'll also need to set default values for month and day so that they are not required in the 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}" } 
);

And in your controller action check if the month or day are 0, in which case you should show an entire month or entire year.

墟烟 2024-08-29 20:00:27

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

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

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}"}
);

有几种方法可以处理这种情况,但现在在您的博客控制器和索引操作中,您可以按年份过滤帖子结果,月、日。

简单的例子:

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

...

The other issue I see you running into is that you'll need several other route entries with appropriate defaults to handle those other scenarios.

"http://abc.com/2010" will not match "blog/{year}/{month}/{day}". That's a very specific route that requires three parameters (with constraints) to match. In order to accept those other routes you'll need to create other route entries along the lines of:

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}"}
);

There are a few ways to handle this scenario, but now in your Blog controller and your Index action you can filter the posts results by year, month, day.

Quick example:

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

...

给不了的爱 2024-08-29 20:00:27

您不必为所有条件编写新方法。我的意思是你可以用这个来做;

例如。对于 NHibernate。

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();
}

附:它正在逐步检查参数,年份->月->天。如果用户没有在查询字符串中设置任何参数,它将返回所有博客。

You dont have to write new method for all condition. I mean you can do it with this;

eg. for NHibernate.

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();
}

ps. It's checking parameters step by step, year -> month -> day. If user doesnt set any parameters in querystring, it will return all blogs.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文