Генерация канонического автоматически для веб-приложения mvc3 - PullRequest
13 голосов
/ 22 марта 2011

Я хочу использовать канонические ссылки на моем сайте. Я прочитал кое-что об этом в Интернете, но я ищу решение, которое автоматически сгенерирует каноническое для меня время выполнения и добавит его в html-код, возвращаемый браузеру.

Я уже нашел пример в интернете с использованием атрибута, но это не то, что я ищу. Используя атрибут, я все еще решаю, какая страница должна стать канонической или нет, я хочу, чтобы каждая страница генерировалась автоматически. Я так понимаю, должны быть (существующие) решения? Я изо всех сил пытаюсь найти хороший пример для работы, поэтому любая помощь приветствуется.

Ответы [ 4 ]

21 голосов
/ 26 марта 2011

Для Razor:

Я сделал один метод расширения для 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));
}

Чтобы получить текущий URL

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 View:

@Html.CanonicalUrl()
4 голосов
/ 30 сентября 2014

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 голосов
/ 15 декабря 2016

Принятый ответ, хотя он обеспечивает хороший способ создания канонических URL.

Это ярлык, чтобы выстрелить себе в ногу !!

Это полностью уничтожает смысл использования канонического тега!

Почему существует канонический тег?

Когда 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) и создайте ссылки с единственной вещью, которая идентифицирует одну страницу. И это ваши Контроллер / Действие (А может быть язык ) Комбинации. Таким образом, вы можете извлечь эти значения из ваших данных маршрута .

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 ответил на это.

Затем, чтобы сгенерировать теги Canonical для всех страниц, вы должны либо сделать расширение 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)
1 голос
/ 22 марта 2011

Проблема решена. Исправлена ​​ошибка, из-за которой я писал собственный помощник html, который генерирует канонический URL-адрес, беря URL-адреса из запроса. Сделал это, используя информацию из этой темы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...