Принятый ответ, хотя он обеспечивает хороший способ создания канонических 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)