Создание канонического автоматически для web-приложения mvc3

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

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

Ответ 1

Для бритвы:

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

Ответ 2

MVC 5 имеет новую возможность генерации URL нижнего регистра для ваших маршрутов. Конфигурация моего маршрута показана ниже:

public static class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        // Imprive SEO by stopping duplicate URL 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-адрес, как это сделано для вас. Единственная проблема может возникнуть, если вы используете URL-адрес HTTP и HTTPS и хотите использовать для этого канонический URL-адрес. В этом случае довольно просто использовать вышеупомянутый подход и заменить HTTP HTTPS или наоборот.

Ответ 3

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

Ответ 4

Принятый ответ, хотя он обеспечивает хороший способ создания канонических 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="#" onclick="location.href='http://yourdomain.com'; return false;" rel="canonical">Да... это другая страница, сканирующая этот тоже.... <link href="#" onclick="location.href='http://www.yourdomain.com/index'; return false;" 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 ответил на это.

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