Как избежать дублирования контента в ASP.NET MVC из-за URL-адресов, нечувствительных к регистру, и значений по умолчанию?

StackOverflow https://stackoverflow.com/questions/170900

  •  05-07-2019
  •  | 
  •  

Вопрос

Редактировать:Теперь мне нужно решить эту проблему по-настоящему, я сделал немного больше расследование и придумал с количество вещей для уменьшения дубликатов содержание.Я выложил подробный код образцы в моем блоге: Сокращение Дублирование контента с помощью ASP.NET MVC

Первый пост. Будьте проще, если я неправильно его разметил или неправильно отметил. :P

В новой платформе ASP.NET MVC от Microsoft, похоже, есть две вещи, которые могут привести к тому, что ваш контент будет отображаться по нескольким URL-адресам (за что Google наказывает и приведет к разделению вашего PageRank между ними):

  • URL-адреса без учета регистра
  • URL-адрес по умолчанию

Вы можете установить контроллер/действие по умолчанию для обработки запросов к корню вашего домена.Допустим, мы выбираем HomeController/Index.В итоге мы получаем следующие URL-адреса, предоставляющие один и тот же контент:

  • mydomain.com/
  • mydomain.com/Главная/Индекс

Теперь, если люди начнут ссылаться на оба из них, PageRank будет разделен.Google также будет считать это дублирующим контентом и наказывать одного из них, чтобы избежать дублирования результатов.

Кроме того, URL-адреса не чувствительны к регистру, поэтому мы фактически получаем один и тот же контент для этих URL-адресов:

  • mydomain.com/Главная/Индекс
  • мойдомен.com/home/index
  • mydomain.com/Home/index
  • mydomain.com/home/Index
  • (список можно продолжить)

Итак, вопрос...Как мне избежать этих наказаний?Я хотел бы:

  • Все запросы на действие по умолчанию будут перенаправлены (статус 301) на один и тот же URL-адрес.
  • Все URL-адреса должны быть чувствительны к регистру

Возможный?

Это было полезно?

Решение

Ударяться!

МВК 5 Теперь поддерживается создание только строчных URL-адресов и общая политика косой черты в конце.

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.LowercaseUrls = true;
        routes.AppendTrailingSlash = false;
     }

Также в моем приложении, чтобы избежать дублирования контента в разных доменах/IP-адресах/регистре букв и т. д.

http://вашдомен.com/en

https://yourClientIdAt.YourHostingPacket.com/

Я склонен создавать канонические URL-адреса на основе Первичныйдомен - Протокол - Контроллер - Язык - Действие

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);
}

Тогда вы можете использовать @Гейб Самнер ответ для перенаправления на канонический URL-адрес вашего действия, если текущий URL-адрес запроса не соответствует ему.

Другие советы

Я тоже работал над этим.Я, очевидно, подчинюсь в этом Скотту.Однако я смиренно предлагаю свое решение и этой проблемы.

Добавьте следующий код в 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();
    }
}

Отличный вопрос!

Помимо публикации здесь, я отправил электронное письмо Скотту Гу, чтобы узнать, получил ли он хороший ответ.Он привел пример добавления ограничений к маршрутам, чтобы вы могли отвечать только на 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() }
    );
}

Это начало, но хотелось бы иметь возможность изменить генерацию ссылок с помощью таких методов, как Html.ActionLink и RedirectToAction, чтобы они соответствовали.

Я считаю, что на этот вопрос есть лучший ответ.Если вы поместите каноническую ссылку в заголовок страницы, например:

<link rel="canonical" href="http://mydomain.com/Home/Index"/>

Тогда Google показывает в своих результатах только каноническую страницу, и, что более важно, все преимущества Google попадают на эту страницу без каких-либо штрафов.

Как ты, У меня такой же вопрос;за исключением того, что я не хотел соглашаться на ограничение URL-адреса, состоящего только из строчных букв, и мне не нравилось canonical подход либо (ну, это хорошо, но не само по себе).

Я не смог найти решение, поэтому мы написал и открыл исходный код а класс перенаправления.

Использовать его достаточно просто:каждый метод GET в классах контроллера должен добавить только одну строку в начале:

Seo.SeoRedirect(this);

Класс перезаписи SEO автоматически использует атрибуты информации о вызывающем абоненте C# 5.0 для выполнения тяжелой работы, что делает приведенный выше код строго копируемым и вставляемым.

Как я уже упоминал в связанных вопросах и ответах по SO, я работаю над тем, как преобразовать это в атрибут, но на данный момент он выполняет свою работу.

Код будет принудительно использовать один регистр для URL-адреса.Регистр будет таким же, как и в названии метода контроллера — вы выбираете, хотите ли вы использовать все прописные буквы, все нижние или сочетание того и другого (CamelCase подходит для URL-адресов).Он выдает 301 перенаправление для совпадений без учета регистра и кэширует результаты в памяти для обеспечения максимальной производительности.Он также перенаправляет конечные обратные косые черты (принудительно для списков индексов, в противном случае принудительно отключается) и удаляет дублирующийся контент, доступ к которому осуществляется через имя метода по умолчанию (Index в стандартном приложении ASP.NET MVC).

я действительно не знаю, как вы будете себя чувствовать через 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();
    }

На основе ответа Гейба Самнера, но без перенаправлений для JS, изображений и другого контента.Работает только на действиях контроллера.Идея состоит в том, чтобы выполнить перенаправление позже в конвейере, когда мы уже знаем его маршрут.Для этого мы можем использовать ActionFilter.

public class RedirectFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var url = filterContext.HttpContext.Request.Url;
        var urlWithoutQuery = url.GetLeftPart(UriPartial.Path);
        if (Regex.IsMatch(urlWithoutQuery, @"[A-Z]"))
        {
            string lowercaseURL = urlWithoutQuery.ToString().ToLower() + url.Query;
            filterContext.Result = new RedirectResult(lowercaseURL, permanent: true);
        }

        base.OnActionExecuting(filterContext);
    }
}

Обратите внимание, что приведенный выше фильтр не перенаправляет и не меняет регистр строки запроса.

Затем глобально привяжите ActionFilter ко всем действиям, добавив его в GlobalFilterCollection.

filters.Add(new RedirectFilterAttribute());

Рекомендуется по-прежнему устанавливать для свойства LowercaseUrls значение true в RouteCollection.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top