【问题标题】:Generating an canonical automatically for mvc3 webapplication为 mvc3 webapplication 自动生成规范
【发布时间】:2011-07-20 18:48:20
【问题描述】:

我想在我的网站中使用规范网址。我在互联网上阅读了一些关于它的东西,但我正在寻找一种解决方案,它会自动为我的运行时生成规范并将其添加到返回给浏览器的 html 代码中。

我已经在互联网上找到了一个使用属性的示例,但这不是我想要的。使用一个属性,我仍在决定哪个页面应该获得规范或不是我自己,我希望每个页面都有一个自动生成。我认为应该有(现有的)解决方案?我正在努力寻找一个很好的例子来工作,所以任何帮助都非常感谢。

【问题讨论】:

    标签: c# asp.net asp.net-mvc-3 seo


    【解决方案1】:

    虽然它提供了一种生成规范网址的好方法,但已被接受。

    这是自取其辱的捷径!!

    完全破坏了使用canonical标签的意义!

    为什么存在规范标签?

    当 google 抓取您的网站并发现重复的内容时,您会受到惩罚。

    可以通过各种路径访问您网站中的同一页面。

    http://yourdomain.com/en
    https://yourClientIdAt.YourHostingPacket.com/
    http://195.287.xxx.xxx  //Your server Ip
    https://yourdomain.com/index
    http://www.yourdomain.com/
    http://www.yourdomain.com/index  .....etc... etc..
    

    Google 会在各种路径中找到相同的内容,从而重复内容,从而受到惩罚。

    虽然最好的做法是使用 301 重定向并且只有 1 个链接指向同一个网页,这很痛苦......

    这就是创建 rel="canonical" 的原因。它是一种告诉爬虫的方法

    “嘿,这不是一个不同的页面,这是 www.mydomain.index 页面 您之前搜索过....规范标签中的链接是正确的!”

    这样同一个网页就不会被多次抓取为不同的网页。

    通过从你刚才说的 url 动态生成规范链接....

    <link href="http://yourdomain.com" rel="canonical"> 是的....这是一个不同的页面抓取这个也是.... <link href="http://www.yourdomain.com/index" rel="canonical">这是一个不同的......而这个......

    因此,为了获得有效的规范标签,您必须为每个具有不同内容的页面生成完全相同的链接。确定您的主要(www.etc.com)、协议 (Https/Http) 和Letter Casing(/Index,/index) 并生成与唯一符合以下条件的内容的链接标识单个页面。 这是您的Controller/Action(也许还有language)组合。 因此,您可以从您的路线数据中提取这些值。

    public static TagBuilder 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();
        string finalUrl = String.Format("{0}://{1}/{2}/{3}/{4}", protocol, host, language, controllerName, actionName);
    
        var canonical = new TagBuilder("link");
        canonical.MergeAttribute("href", finalUrl);
        canonical.MergeAttribute("rel", "canonical");
        return canonical;
    }
    

    为了让您的 HtmlHelper 生成与您的约定一致的链接,@Muhammad Rehan Saeed 回答了这个问题。

    然后,为了为所有页面生成规范标签,您必须制作 HtmlHelper 扩展

    public static MvcHtmlString CanonicalUrl(this HtmlHelper html,string host,string protocol)
    {
        var canonical = GetCanonicalUrl(HttpContext.Current.Request.RequestContext.RouteData,host,protocol);
        return new MvcHtmlString(canonical.ToString(TagRenderMode.SelfClosing));
    }
    
    
    @Html.CanonicalUrl("www.mydomain.com", "https");
    

    或者为你的控制器实现一个动作过滤器属性。 (我使用这种方法是为了在同一个应用程序上处理具有多个域的更复杂的场景等......)

        public class CanonicalUrl : ActionFilterAttribute
        {
            private string _protocol;
            private string _host;
            public CanonicalUrl(string host, string protocol)
            {
                this._host = host;
                this._protocol = protocol;
            }
            public override void OnResultExecuting(ResultExecutingContext filterContext)
            {
                var canonical = GetCanonicalUrl(filterContext.RouteData,_host,_protocol);
                filterContext.Controller.ViewBag.CanonicalUrl = canonical.ToString();
            }
        }
    }
    

    在控制器中使用

    [CanonicalUrl("www.yourdomain.com","https")]
    public class MyController : Controller
    

    然后我在我的 _Layout.chtml 上使用它并完成了!

    @Html.Raw(ViewBag.CanonicalUrl)
    

    【讨论】:

      【解决方案2】:

      MVC 5 具有为您的路由生成小写 URL 的新选项。我的路线配置如下所示:

      public static class RouteConfig
      {
          public static void RegisterRoutes(RouteCollection routes)
          {
              // Imprive SEO by stopping duplicate URL's due to case or trailing slashes.
              routes.AppendTrailingSlash = true;
              routes.LowercaseUrls = true;
      
              routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
      
              routes.MapRoute(
                  name: "Default",
                  url: "{controller}/{action}/{id}",
                  defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
          }
      }
      

      使用此代码,您将不再需要规范化 URL,因为这是为您完成的。如果您使用的是 HTTP 和 HTTPS URL,并且需要一个规范的 URL,则可能会出现唯一的问题。在这种情况下,很容易使用上述方法并将 HTTP 替换为 HTTPS,反之亦然。

      【讨论】:

        【解决方案3】:

        对于剃刀:

        我为HtmlHelper做了一种扩展方法:

        public static MvcHtmlString CanonicalUrl(this HtmlHelper html, string path)
        {
            if (String.IsNullOrWhiteSpace(path))
            {
                var rawUrl = html.ViewContext.RequestContext.HttpContext.Request.Url;
                path = String.Format("{0}://{1}{2}", rawUrl.Scheme, rawUrl.Host, rawUrl.AbsolutePath);
            }
        
            path = path.ToLower();
        
            if (path.Count(c => c == '/') > 3)
            {
                path = path.TrimEnd('/');
            }
        
            if (path.EndsWith("/index"))
            {
                path = path.Substring(0, path.Length - 6);
            }
        
            var canonical = new TagBuilder("link");
            canonical.MergeAttribute("rel", "canonical");
            canonical.MergeAttribute("href", path);
            return new MvcHtmlString(canonical.ToString(TagRenderMode.SelfClosing));
        }
        

        获取当前网址

        public static MvcHtmlString CanonicalUrl(this HtmlHelper html)
        {
            var rawUrl = html.ViewContext.RequestContext.HttpContext.Request.Url;
        
            return CanonicalUrl(html, String.Format("{0}://{1}{2}", rawUrl.Scheme, rawUrl.Host, rawUrl.AbsolutePath));
        }
        

        调用 Razor 视图:

        @Html.CanonicalUrl()
        

        【讨论】:

        • 这是一个很好的解决方案!完美运行!用你的第一个解决方案替换了我自己的扩展。
        • 我意识到我在评论一个已有一年的问题,但这只是将地址栏中的当前 URL 复制到 rel=canonical 标记。这对帮助搜索引擎确定该页面的正确 URL 没有任何帮助,因为无论当前 URL 是什么,都将显示为该页面的规范 URL。这有点自欺欺人。属性方法有什么问题?这似乎是这样做的合乎逻辑的方式。为控制器中的每个 Action 定义一次,无论当前 URL 是什么,它的 URL 都应该是什么,这就是它。
        • @Scott 我认为你错过了重点。规范 URL 的目的是告诉索引引擎(即:google)几个 URI 实际上是同一件事,并且您有一个首选的索引 URI。上面的代码将删除任何查询字符串数据,对索引 URI 进行重复数据删除,并在 URI 中的根域之外强制执行任何尾随斜杠(更多重复数据删除)。在你告诉每个人你认为它做什么/不做什么之前,自己去试试吧!另外,您可以扩展上述内容以保留某些查询字符串或强制使用 www 之类的子域。确实很有用!
        • 其实我自己试过了,这个解决方案是在我写的一个现场网站中实现的。 :) 经过一些实验,它根本没有按预期工作。使用不同的主机标头启动同一站点会导致新 URL 显示为规范 URL(换句话说,规范 URL 是地址栏中的任何内容,而不是不变的静态值)。跨度>
        • @Scott 您可以在扩展方法中更改主机吗?
        【解决方案4】:

        问题解决了。修复了它编写我自己的 html 帮助程序,该帮助程序通过从请求中获取 url 来生成规范的 url。使用来自this 主题的信息进行此操作。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-10-24
          • 1970-01-01
          • 2011-02-10
          • 2016-09-09
          • 1970-01-01
          • 2021-10-15
          • 1970-01-01
          • 2012-11-16
          相关资源
          最近更新 更多