Создание канонического автоматически для 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)