2011-05-19 86 views
31

如果缺少部分URL,如何将ASP.NET MVC中的请求重定向到正确的规范版本?向ASP.NET MVC中的URL slugs添加标识和标题

以堆栈溢出为例,该站点将问题标题添加到其路径的末尾,但在路径中使用问题标识来实际查找问题。如果标题被忽略,您将被重定向到正确的URL。

例如,访问的网址:

stackoverflow.com/questions/9033 

会重定向到

stackoverflow.com/questions/9033/hidden-features-of-c 

这是如何工作的?

+4

看到这个相关的问题和答案http://stackoverflow.com/questions/2174820/how-to-add-page-title-in-url-in-asp-net-mvc-url-generation和http:/ /stackoverflow.com/questions/677158/stackoverover-question-routing – jao 2011-05-19 07:51:15

回答

38

首先创建一个路由:

routes.MapRoute( 
    "ViewProduct", 
    "Products/{id}/{productName}", 
    new { controller = "Product", action = "Details", id = "", productName = "" } 
); 

然后创建操作方法如下所示:

public ActionResult Details(int? id, string productName) 
{ 
    Product product = ProductRepository.Fetch(id); 

    string realTitle = UrlEncoder.ToFriendlyUrl(product.Title); 
    string urlTitle = (productName ?? "").Trim().ToLower(); 

    if (realTitle != urlTitle) 
    { 
     string url = "/Products/" + product.Id + "/" + realTitle; 
     return new PermanentRedirectResult(url); 
    } 

    return View(product); 
} 

你基本上在URL与一个存储在数据库中比较实体名称,如果它们不匹配,则执行301永久重定向。确保它是一个'永久'重定向(301状态码),而不是临时重定向(302)。这样,搜索引擎会将其视为网址的永久变更,并相应地更新其索引,如果实体的标题在搜索引擎编入索引后发生变化(例如,某人更改了产品名称),则可能会发生这种情况。

另一件需要注意的事情是,如果您的标题允许任何自由文本,您需要删除任何对URL无效的字符,并使其对人类和搜索引擎更具可读性,因此UrlEncoder.ToFriendlyUrl在上面的代码方法,实现的过程如下:

public static class UrlEncoder 
{ 
    public static string ToFriendlyUrl (this UrlHelper helper, 
     string urlToEncode) 
    { 
     urlToEncode = (urlToEncode ?? "").Trim().ToLower(); 

     StringBuilder url = new StringBuilder(); 

     foreach (char ch in urlToEncode) 
     { 
      switch (ch) 
      { 
       case ' ': 
        url.Append('-'); 
        break; 
       case '&': 
        url.Append("and"); 
        break; 
       case '\'': 
        break; 
       default: 
        if ((ch >= '0' && ch <= '9') || 
         (ch >= 'a' && ch <= 'z')) 
        { 
         url.Append(ch); 
        } 
        else 
        { 
         url.Append('-'); 
        } 
        break; 
      } 
     } 

     return url.ToString(); 
    } 
} 

所以,当你写出来的网址进入查看时,一定要使用这种方法如编码标题

<a href="/Products/@Model.Id/@Url.ToFriendlyUrl(Model.Title)">@Model.Title</a> 

我写这个博客张贴在这里http://www.dominicpettifer.co.uk/Blog/34/asp-net-mvc-and-clean-seo-friendly-urls

+3

Stackoverflow的创建者在这里显示他的'ToFriendlyUrl'的实现:[http://stackoverflow.com/questions/25259/how-do-you-包括-A-网页标题-AS-部分对的一网页的URL/25486#25486](http://stackoverflow.com/questions/25259/how-do-you-include-a-webpage-title -as-part-of-a-page-url/25486#25486) – wycleffsean 2011-11-07 19:12:01

+1

URL中UTF-8字符的标准已更改。根据[Wikipedia](http://en.wikipedia.org/wiki/Internationalized_domain_name),Mozilla 1.4,Netscape 7.1,Opera 7.11是首批支持IDNA的应用程序之一。浏览器插件可用于Internet Explorer 6以提供IDN支持。 Internet Explorer 7.0和Windows Vista的URL API为IDN提供本机支持。听起来像删除UTF-8字符是浪费时间。万岁UTF-8 !!! – 2015-04-24 14:18:25

+1

我用小提琴手,注意到Stackoverflow.com做一个'302' - 临时重定向从'stackoverflow.com/questions/9033'到'stackoverflow.com/questions/9033/hidden-features-of-c'如何解释那是因为你说重定向应该是'301' - 永久重定向? – Shiva 2017-05-09 05:21:48

3

虽然我不知道StackOverflow如何管理它的任何细节,但下面概述了如何实现做到这一点

  • 使用的ID从数据库中检索的问题
  • 转换存储问题的标题为URL兼容塞
  • 如果转换的标题塞不匹配的URL通过了塞然后重定向使用转换后的标题slu。。

这将确保URL是永远正确的,避免possible embarrassing fake URLs

+0

更新的答案突出显示,slug实际上是由问题标题以及为什么重要的是检查URL中传递的slu is实际上是正确的slu slu。 – 2011-05-19 09:19:42

0

这里是他们如何可能做到这一点,但我相信你问它是如何做,这应该工作的例子。

第一阶段是建立2路在Global.asax

routes.MapRoute("WithQuestion", "questions/{id}/{name}", new { controller = "Questions", action = "Question", id = "1" }); 
routes.MapRoute("WithoutQuestion", "questions/{id}", new { controller = "Questions", action = "WithoutQuestion", id="1"}); 

现在我们的问题控制器,

public ActionResult Question(int id) 
    { 
     //Load the question as we have the name appended. 
     // We could actually do a little validation here as well 
     return View(); 
    } 

    public ActionResult WithoutQuestion(int id) 
    { 
     //Load the question object 
     //Generate the full URL and redirect 
     return Redirect(FullURL) 
    } 

这是一个非常基本的例子,但说明了如何能做到它。

+1

您的示例并不完全正确,如果使用不正确的slug,则StackOverflow将始终重定向到正确的slug,例如http://stackoverflow.com/questions/6055415/totally-made-up-slug所以因此需要检查URL中传递的slu is实际上是存储在数据库中的正确slu slu。 – 2011-05-19 09:08:07

+0

@David //我们实际上也可以在这里做一些验证;) – LiamB 2011-05-19 12:46:39

0

@sunday我已经尝试过了,但我仍然面临着问题。我需要给URL作为

产品?ID = 4 &产品名称=新博客

然后我得到了解决。 This帮了我。我们需要确保CUSTOM路线高于默认路线

现在它工作正常。