如果缺少部分网址,如何将ASP.NET MVC中的请求重定向到正确的规范版本?
使用Stack Overflow作为示例,站点将问题标题添加到其路径的末尾,但使用路径中的问题ID来实际查找问题。如果省略标题,您将被重定向到正确的URL。
例如,访问网址:
stackoverflow.com/questions/9033
将重定向到
stackoverflow.com/questions/9033/hidden-features-of-c
这是如何运作的?
答案 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如何管理它的任何细节,但这里概述了如何做到这一点
这可确保网址始终正确,并避免使用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)
产品ID = 4&安培;产品名称=新博客
然后我得到了解决方案。This帮助了我。我们需要确保CUSTOM路由超出默认路由
现在工作正常。