Comment éviter le contenu en double dans ASP.NET MVC en raison d'URL et de valeurs par défaut non sensibles à la casse?

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

  •  05-07-2019
  •  | 
  •  

Question

  

Modifier : Maintenant, je dois résoudre ce problème pour de vrai, j'ai fait un peu plus   enquête et est venu avec un   nombre de choses à réduire les doublons   contenu. J'ai posté un code détaillé   exemples sur mon blog: Réduire   Dupliquer le contenu avec ASP.NET MVC

Premier message - allez-y doucement si j'ai mal marqué ou mal marqué: P

Dans la nouvelle infrastructure ASP.NET MVC de Microsoft, deux éléments peuvent provoquer la diffusion de votre contenu sur plusieurs URL (un élément que Google pénalise et qui divise votre PageRank):

  • URL insensibles à la casse
  • URL par défaut

Vous pouvez configurer le contrôleur / l'action par défaut pour qu'il réponde aux demandes adressées à la racine de votre domaine. Disons que nous choisissons HomeController / Index. Les URL suivantes servent le même contenu:

  • mydomain.com /
  • mydomain.com/Home/Index

Maintenant, si les gens commencent à créer un lien vers ces deux éléments, le PageRank sera divisé. Google envisagerait également de dupliquer le contenu et de pénaliser l’un d’eux pour éviter les doublons dans leurs résultats.

De plus, les URL ne sont pas sensibles à la casse. Nous obtenons donc le même contenu pour ces URL:

  • mydomain.com/Home/Index
  • mydomain.com/home/index
  • mydomain.com/Home/index
  • mydomain.com/home/Index
  • (la liste continue)

Alors, la question ... Comment puis-je éviter ces pénalités? Je voudrais:

  • Toutes les demandes pour que l'action par défaut soit redirigée (statut 301) vers la même URL
  • Toutes les URL doivent être sensibles à la casse

Possible?

Était-ce utile?

La solution

Bump!

MVC 5 prend désormais en charge la production uniquement d'URL en minuscules et d'une stratégie de barre oblique de fin courante.

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

Également sur ma candidature pour éviter la duplication de contenu sur différents domaines / IP / Letter Box, etc. ...

  

http://yourdomain.com/en

     

https://yourClientIdAt.YourHostingPacket.com/

J'ai tendance à produire des URL canoniques basées sur un PrimaryDomain - protocole - contrôleur - Langue - > Action

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

Ensuite, vous pouvez utiliser la réponse @Gabe Sumner pour rediriger vers l'URL canonique de votre action si l'URL de la requête en cours ne correspond pas.

Autres conseils

Je travaillais aussi là-dessus. Je vais évidemment laisser la parole à ScottGu à ce sujet. J’offre humblement ma solution à ce problème également.

Ajoutez le code suivant à 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();
    }
}

Une bonne question!

En plus de poster ici, j’ai envoyé un courriel à ScottGu pour savoir s’il avait une bonne réponse. Il a donné un exemple pour ajouter des contraintes aux itinéraires, afin que vous puissiez uniquement répondre aux URLs minuscules:

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

Et dans la méthode des routes de registre:

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

C'est un début, mais j'aimerais pouvoir modifier la génération de liens à partir de méthodes telles que Html.ActionLink et RedirectToAction afin qu'elles correspondent.

Je pense qu’il existe une meilleure réponse à cette question. Si vous insérez un lien canonique dans l'en-tête de votre page, par exemple:

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

Ensuite, Google ne montre que la page canonique dans ses résultats et, plus important encore, tout le bien de Google va à cette page sans pénalité.

Comme vous, j'avais la même question ; sauf que je ne voulais pas me contenter d'une limitation d'URL tout en minuscules et que je n'aimais pas l'approche canonique non plus (eh bien, c'est bon mais pas tout seul).

Je ne pouvais pas trouver de solution. Nous avons donc écrit et ouvert à la source un classe de redirection .

Son utilisation est assez simple: chaque méthode GET dans les classes du contrôleur doit ajouter uniquement cette ligne au début:

Seo.SeoRedirect(this);

La classe de réécriture SEO utilise automatiquement les attributs Informations de l'appelant de C # 5.0 pour faire le gros du travail, rendant le code ci-dessus strictement copié-collé.

Comme je l'ai mentionné dans le Q & A lié au SO, je cherche un moyen de convertir cet attribut en attribut, mais pour l'instant, le travail est fait.

Le code forcera un cas pour l'URL. Le cas sera le même que le nom de la méthode du contrôleur - vous choisissez si vous souhaitez utiliser toutes les majuscules, toutes les majuscules ou un mélange des deux (CamelCase convient aux URL). Il émettra des redirections 301 pour les correspondances sans distinction de casse et mettra les résultats en mémoire cache pour une performance optimale. Il va également rediriger les barres obliques inverses (appliquées pour les listes d'index, sinon désactivées) et supprimer le contenu dupliqué accessible via le nom de méthode par défaut ( Index dans une application stock ASP.NET MVC).

Je ne sais vraiment pas comment vous allez vous sentir après 8 ans, mais maintenant, ASP MVC 5 prend en charge le routage par attribut pour des routes faciles à mémoriser et pour résoudre les problèmes de contenu en double pour les sites orientés SEO Friendly

ajouter itinéraires.MapMvcAttributeRoutes (); dans votre RouteConfig, puis définissez un et un seul itinéraire pour chaque action, comme

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

Sur la base de la réponse de Gabe Sumner, mais sans redirections pour JS, images et autres contenus. Ne fonctionne que sur les actions du contrôleur. L'idée est de faire la redirection plus tard dans le pipeline quand on sait déjà que c'est un itinéraire. Pour cela, nous pouvons utiliser un 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);
    }
}

Notez que le filtre ci-dessus ne redirige ni ne modifie la casse de la chaîne de requête.

Liez ensuite ActionFilter globalement à toutes les actions en l'ajoutant à GlobalFilterCollection.

filters.Add(new RedirectFilterAttribute());

Il est judicieux de toujours définir la propriété LowercaseUrls sur true sur RouteCollection.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top