由于不区分大小写的URL和默认值,我如何避免ASP.NET MVC中的重复内容?

时间:2008-10-04 19:32:09

标签: c# asp.net asp.net-mvc razor

  

编辑:现在我需要真正解决这个问题,我做了一点   调查并想出了一个   减少重复的事情数量   内容。我发布了详细的代码   我博客上的示例:Reducing Duplicate Content with ASP.NET MVC

第一篇文章 - 如果我标记错误或标记错误,请轻松一下:P

在微软新的ASP.NET MVC框架中,似乎有两件事可能会导致您的内容在多个网址上提供(Google会对此进行惩罚,并导致您的PageRank在其中分割):

  • 不区分大小写的网址
  • 默认网址

您可以设置默认控制器/操作以提供对域根目录的请求。假设我们选择HomeController / Index。我们最终提供了以下提供相同内容的网址:

  • mydomain.com /
  • mydomain.com/Home/Index

现在,如果人们开始链接到这两者,那么PageRank将被拆分。谷歌也会认为它是重复内容并惩罚其中一个,以避免重复结果。

除此之外,这些网址不区分大小写,因此我们实际上也为这些网址获取了相同的内容:

  • mydomain.com/Home/Index
  • mydomain.com/home/index
  • mydomain.com/Home/index
  • mydomain.com/home/Index
  • (列表继续)

所以,问题是......我如何避免这些处罚?我想:

  • 要求将默认操作重定向(301状态)到同一网址
  • 所有区分大小写的网址

可能的?

7 个答案:

答案 0 :(得分:11)

我也在研究这个问题。我显然会顺从ScottGu。我谦卑地提供了解决这个问题的方法。

将以下代码添加到 global.asax

protected void Application_BeginRequest(Object sender, EventArgs e)
{
    // If upper case letters are found in the URL, redirect to lower case URL.
    if (Regex.IsMatch(HttpContext.Current.Request.Url.ToString(), @"[A-Z]") == true)
    {
        string LowercaseURL = HttpContext.Current.Request.Url.ToString().ToLower();

        Response.Clear();
        Response.Status = "301 Moved Permanently";
        Response.AddHeader("Location",LowercaseURL);
        Response.End();
    }
}

一个很好的问题!

答案 1 :(得分:9)

除了在这里发帖,我还通过电子邮件向ScottGu发送电子邮件,看他是否有好的回复。他给出了一个为路由添加约束的示例,因此您只能回复小写网址:

public class LowercaseConstraint : IRouteConstraint
{
    public bool Match(HttpContextBase httpContext, Route route,
            string parameterName, RouteValueDictionary values,
            RouteDirection routeDirection)
    {
        string value = (string)values[parameterName];

        return Equals(value, value.ToLower());
    }

在寄存器路由方法中:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
        "Default",                                              // Route name
        "{controller}/{action}/{id}",                           // URL with parameters
        new { controller = "home", action = "index", id = "" },
        new { controller = new LowercaseConstraint(), action = new LowercaseConstraint() }
    );
}

这是一个开始,但是我希望能够从Html.ActionLink和RedirectToAction等方法更改链接的生成以匹配。

答案 2 :(得分:4)

凹凸!

MVC 5 现在支持仅生成小写网址和常见的尾部斜杠政策。

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.LowercaseUrls = true;
        routes.AppendTrailingSlash = false;
     }

同样在我的申请中,以避免在不同的域名/ Ip / Letter Casing等上重复内容...

  

http://yourdomain.com/en

     

https://yourClientIdAt.YourHostingPacket.com/

我倾向于根据 PrimaryDomain - 协议 - 控制器 - 语言 - 动作

public static String GetCanonicalUrl(RouteData route,String host,string protocol)
{
    //These rely on the convention that all your links will be lowercase! 
    string actionName = route.Values["action"].ToString().ToLower();
    string controllerName = route.Values["controller"].ToString().ToLower();
    //If your app is multilanguage and your route contains a language parameter then lowercase it also to prevent EN/en/ etc....
    //string language = route.Values["language"].ToString().ToLower();
    return String.Format("{0}://{1}/{2}/{3}/{4}", protocol, host, language, controllerName, actionName);
}

然后,如果当前请求网址与之匹配,您可以使用 @Gabe Sumner 答案重定向到您操作的规范网址。

答案 3 :(得分:2)

我相信有更好的答案。如果您在页面中添加规范链接,请执行以下操作:

<link rel="canonical" href="http://mydomain.com/Home/Index"/>

然后谷歌只显示其结果中的规范页面,更重要的是,所有谷歌善良都会转到该页面而不会受到惩罚。

答案 4 :(得分:1)

和你一样,I had the same question;除了我不愿满足于全小写的网址限制,并且不喜欢canonical方法(嗯,它很好,但不是单独的)。

我找不到解决方案,所以我们wrote and open-sourced一个redirect class

使用它很容易:控制器类中的每个GET方法都需要在开头添加这一行:

Seo.SeoRedirect(this);

SEO重写类自动使用C#5.0的Caller Info属性来完成繁重的工作,使上面的代码严格复制粘贴。

正如我在链接的SO Q&amp; A中所提到的,我正在研究如何将其转换为属性,但就目前而言,它可以完成工作。

代码将强制一个URL的案例。该案例将与控制器方法的名称相同 - 您可以选择是否要全部大写,全部更低,或两者兼而有(CamelCase适用于URL)。它将针对不区分大小写的匹配发出301重定向,并将结果缓存在内存中以获得最佳性能。它还会重定向尾随反斜杠(强制执行索引列表,否则强制执行),并删除通过默认方法名称(库存ASP.NET MVC应用程序中的Index)访问的重复内容。

答案 5 :(得分:0)

我真的不知道你8年后会有什么感受但现在ASP MVC 5支持易于记忆路线的属性路由,并解决了SEO友好网站的重复内容问题

添加 routes.MapMvcAttributeRoutes();在RouteConfig中,然后为每个操作定义一个且唯一的路由,如

    [Route("~/")]
    public ActionResult Index(int? page)
    {
        var query = from p in db.Posts orderby p.post_date descending select p;
        var pageNumber = page ?? 1;
        ViewData["Posts"] = query.ToPagedList(pageNumber, 7);         
        return View();
    }
    [Route("about")]
    public ActionResult About()
    {
        return View();
    }
    [Route("contact")]
    public ActionResult Contact()
    {
        return View();
    }
    [Route("team")]
    public ActionResult Team()
    {
        return View();
    }
    [Route("services")]
    public ActionResult Services()
    {
        return View();
    }

答案 6 :(得分:0)

基于Gabe Sumner的回答,但没有重定向JS,图像和其他内容。仅适用于控制器动作。这个想法是在我们已经知道路由的路由时,在管道的后面进行重定向。为此,我们可以使用ActionFilter。

public class RedirectFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var url = filterContext.HttpContext.Request.Url;
        var urlWithoutQuery = url.GetLeftPart(UriPartial.Path);
        if (Regex.IsMatch(urlWithoutQuery, @"[A-Z]"))
        {
            string lowercaseURL = urlWithoutQuery.ToString().ToLower() + url.Query;
            filterContext.Result = new RedirectResult(lowercaseURL, permanent: true);
        }

        base.OnActionExecuting(filterContext);
    }
}

请注意,上面的过滤器不会重定向或更改查询字符串的大小写。

然后将ActionFilter全局绑定到所有动作,方法是将其添加到GlobalFilterCollection。

filters.Add(new RedirectFilterAttribute());

在RouteCollection上仍将LowercaseUrls属性设置为true是个好主意。