Как избежать дублирования содержимого в ASP.NET MVC из-за нечувствительных к регистру URL-адресов и значений по умолчанию?
Изменить: теперь мне нужно решить эту проблему на самом деле, я сделал немного больше расследования и придумали количество вещей, чтобы уменьшить дубликат содержание. Я отправил подробный код образцы в моем блоге: Уменьшение Дублирование содержимого с помощью ASP.NET MVC
Первое сообщение - легко, если я отметил это неправильно или неправильно помечен: P
В новой структуре ASP.NET MVC Microsoft кажется, что есть две вещи, которые могут привести к тому, что ваш контент будет обслуживаться по нескольким URL-адресам (то, за что Google наказывает и приведет к разрыву вашего PageRank):
- Нечувствительные к регистру URL-адреса
- URL по умолчанию
Вы можете установить контроллер/действие по умолчанию для обслуживания запросов к корню вашего домена. Скажем, мы выбираем HomeController/Index. В результате мы получаем следующие URL-адреса, обслуживающие один и тот же контент:
- mydomain.com/
- mydomain.com/Home/Index
Теперь, если люди начнут связываться с обоими из них, тогда PageRank будет разделен. Google также рассматривал бы это дублирование контента и наказывал одного из них, чтобы избежать дублирования результатов.
Кроме того, URL-адреса не чувствительны к регистру, поэтому мы фактически получаем один и тот же контент для этих URL-адресов:
- mydomain.com/Home/Index
- mydomain.com/home/index
- mydomain.com/Home/index
- mydomain.com/home/Index
- (список можно продолжить)
Итак, вопрос... Как избежать этих штрафов? Я бы хотел:
- Все запросы для перенаправления по умолчанию (статус 301) на тот же URL
- Все URL-адреса будут чувствительны к регистру.
Возможные?
Ответы
Ответ 1
Bump!
MVC 5. Теперь поддерживается создание только строчных URL-адресов и общей политики косой черты.
public static void RegisterRoutes(RouteCollection routes)
{
routes.LowercaseUrls = true;
routes.AppendTrailingSlash = false;
}
Также в моем приложении избежать дублирования содержимого на разных доменах /Ip/Letter Casing и т.д.
http://yourdomain.com/en
https://yourClientIdAt.YourHostingPacket.com/
Я склонен создавать канонические адреса на основе PrimaryDomain - Протокола - Контроллер - Язык - Действие
public static String 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();
return String.Format("{0}://{1}/{2}/{3}/{4}", protocol, host, language, controllerName, actionName);
}
Затем вы можете использовать ответ @Gabe Sumner для перенаправления на ваш канонический URL-адрес действия, если текущий URL-адрес запроса не соответствует ему.
Ответ 2
Помимо публикации здесь, я отправил по электронной почте ScottGu, чтобы узнать, есть ли у него хороший ответ. Он дал образец для добавления ограничений для маршрутов, поэтому вы можете отвечать только на строчные URL:
public class LowercaseConstraint : IRouteConstraint
{
public bool Match(HttpContextBase httpContext, Route route,
string parameterName, RouteValueDictionary values,
RouteDirection routeDirection)
{
string value = (string)values[parameterName];
return Equals(value, value.ToLower());
}
И в методе меток регистров:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "home", action = "index", id = "" },
new { controller = new LowercaseConstraint(), action = new LowercaseConstraint() }
);
}
Это начало, но 'd хотите иметь возможность изменять генерации ссылок из таких методов, как Html.ActionLink и RedirectToAction, чтобы соответствовать.
Ответ 3
Я тоже работал над этим. Я, очевидно, буду откладывать на ScottGu. Я смиренно предлагаю решение этой проблемы, хотя.
Добавьте следующий код в global.asax:
protected void Application_BeginRequest(Object sender, EventArgs e)
{
// If upper case letters are found in the URL, redirect to lower case URL.
if (Regex.IsMatch(HttpContext.Current.Request.Url.ToString(), @"[A-Z]") == true)
{
string LowercaseURL = HttpContext.Current.Request.Url.ToString().ToLower();
Response.Clear();
Response.Status = "301 Moved Permanently";
Response.AddHeader("Location",LowercaseURL);
Response.End();
}
}
Отличный вопрос!
Ответ 4
Я считаю, что есть лучший ответ на этот вопрос. Если вы поместите каноническую ссылку в свою страницу, как:
<link rel="canonical" href="http://mydomain.com/Home/Index"/>
Затем Google показывает только каноническую страницу в своих результатах, и, что более важно, вся доброта Google идет на эту страницу без штрафа.
Ответ 5
Как и вы, у меня был тот же вопрос; за исключением того, что я не хотел соглашаться на ограничение всех строчных URL-адресов, и мне не понравился подход canonical
(ну, это хорошо, но не само по себе).
Я не мог найти решение, поэтому мы писали и открывали исходники перенаправить класс.
Использование его достаточно просто: каждый метод GET в классах контроллера должен добавить только одну строку в начале:
Seo.SeoRedirect(this);
Класс rewrite для SEO автоматически использует атрибуты Caller Info С# 5.0 для выполнения тяжелой работы, делая код выше строго скопируйте и вставьте.
Как я упоминал в связанном SO Q & A, я работаю над тем, как преобразовать его в атрибут, но на данный момент он выполняет свою работу.
Код заставит одно дело для URL. Случай будет таким же, как имя метода контроллера - вы выбираете, хотите ли вы все кепки, все ниже или сочетание обоих (CamelCase хорош для URL-адресов). Он будет выдавать 301 переадресацию для нечувствительных к регистру совпадений и кэширует результаты в памяти для достижения максимальной производительности. Он также перенаправляет трейлинг-обратную косую черту (применяется для списков индексов, принудительно отключается в противном случае) и удаляет дублирующийся контент, доступ к которому осуществляется по имени метода по умолчанию (Index
в приложении ASP.NET MVC).
Ответ 6
Я действительно не знаю, как вы будете себя чувствовать через 8 лет, но теперь ASP MVC 5 поддерживает маршрутизацию атрибутов для удобного запоминания маршрутов и решения проблем с дублированием контента для сайтов с поддержкой SEO
просто добавьте
routes.MapMvcAttributeRoutes(); в вашем RouteConfig, а затем определите один и только маршрут для каждого действия, например
[Route("~/")]
public ActionResult Index(int? page)
{
var query = from p in db.Posts orderby p.post_date descending select p;
var pageNumber = page ?? 1;
ViewData["Posts"] = query.ToPagedList(pageNumber, 7);
return View();
}
[Route("about")]
public ActionResult About()
{
return View();
}
[Route("contact")]
public ActionResult Contact()
{
return View();
}
[Route("team")]
public ActionResult Team()
{
return View();
}
[Route("services")]
public ActionResult Services()
{
return View();
}