在ASP.NET MVC中为URL slugs添加ID和标题

时间:2011-05-19 07:46:16

标签: asp.net-mvc routes

如果缺少部分网址,如何将ASP.NET MVC中的请求重定向到正确的规范版本?

使用Stack Overflow作为示例,站点将问题标题添加到其路径的末尾,但使用路径中的问题ID来实际查找问题。如果省略标题,您将被重定向到正确的URL。

例如,访问网址:

stackoverflow.com/questions/9033 

将重定向到

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

这是如何运作的?

5 个答案:

答案 0 :(得分:39)

首先创建路线:

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

然后像这样创建Action方法:

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的永久更改,并相应地更新其索引,如果在搜索引擎对其编制索引后实体的标题发生更改(例如,某人更改了产品的名称),则可能会发生这种情况。 / p>

另外需要注意的是,如果你的标题允许任何自由文本,你需要删除任何对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(); 
    } 
}

因此,当您将URL写入View时,请务必使用此方法对标题进行编码,例如

<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

答案 1 :(得分:3)

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

  • 使用ID
  • 从数据库中检索问题
  • 将存储的问题标题转换为URL兼容的slug
  • 如果转换的标题slug与URL中传递的slug不匹配,则使用转换后的标题slug重定向。

这可确保网址始终正确,并避免使用possible embarrassing fake URLs

答案 2 :(得分:0)

您应该了解ASP.net MVC路由机制,因为Stackoverflow使用此技术。这是一个非常复杂的问题,但你会发现很多学习资源,例如:http://weblogs.asp.net/scottgu/archive/2007/12/03/asp-net-mvc-framework-part-2-url-routing.aspx

答案 3 :(得分:0)

以下是他们可能会这样做的一个示例,但我相信您会询问它是如何完成的,这应该可行。

第一阶段是在Global.asax

中设置2条路线
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)
    }

这是一个非常基本的例子,但展示了如何做到这一点。

答案 4 :(得分:0)

@sunday我试过了,但我还是面临着问题。我需要将网址设为

  

产品ID = 4&安培;产品名称=新博客

然后我得到了解决方案。This帮助了我。我们需要确保CUSTOM路由超出默认路由

现在工作正常。