Generating an canonical automatically for mvc3 webapplication

前端 未结 4 1331
生来不讨喜
生来不讨喜 2021-02-04 08:05

I want to use canonical url\'s in my website. I read a few things about it on the internet, but i\'m looking for a solution which will automatically generate the canonical for m

4条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-02-04 08:05

    The accepted answer although it provides a good way to Produce Canonical url's.

    Its a shortcut to shoot yourself in the foot!!

    It completely destroys the meaning of using the canonical tag!

    Why the canonical tag exists?

    When google crawls your website and finds duplicate content penalizes you.

    The same page in your website can be accessed through various paths.

    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 will find the same content within various paths, thus duplicate content, thus penalty.

    While the best practice is to use 301 redirects and have ONLY 1 link point to the same web page that's a pain......

    That's why rel="canonical" has been created. Its a way to tell the crawler

    "Hey this isn't a different page, this is the www.mydomain.index page you searched before.... the link in the canonical tag is the correct one!"

    And then the same webpage won't be crawled multiple times as a different one.

    By dynamically generating the canonical link from the url you are just saying....

    Yes....this is a different page crawl this one also.... and this is a different one.... and this one...

    So in order to have a working canonical tag you have to generate the same exact link for every page that has different content. Decide your primary Domain(www.etc.com), Protocol (Https/Http) and Letter Casing(/Index,/index) and produce links with the only thing that identifies a single page. And this is your Controller/Action (And maybe language) Combinations. So you can extract those values from your route data.

    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;
    }
    

    In order your HtmlHelper to produce consistent links with your convention @Muhammad Rehan Saeed answered that.

    Then in order to generate your Canonical tags for all pages you have to either make a HtmlHelper extension

    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");
    

    Or Implement an action filter attribute for your controllers . (I used this approach in order to handle more complex scenarios with multiple domains on the same app etc...)

        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();
            }
        }
    }
    

    Usage within controller

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

    Then i used it on my _Layout.chtml and done!

    @Html.Raw(ViewBag.CanonicalUrl)
    

提交回复
热议问题