Come posso evitare contenuti duplicati in ASP.NET MVC a causa di URL e valori predefiniti senza distinzione tra maiuscole e minuscole?

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

  •  05-07-2019
  •  | 
  •  

Domanda

  

Modifica : ora devo risolvere davvero questo problema, ho fatto un po 'di più   indagine e venne fuori con a   numero di cose per ridurre i duplicati   soddisfare. Ho pubblicato un codice dettagliato   esempi sul mio blog: Riduzione   Contenuto duplicato con ASP.NET MVC

Primo post: vai facile se l'ho contrassegnato come sbagliato o se l'ho taggato male: P

Nel nuovo framework ASP.NET MVC di Microsoft sembra che ci siano due cose che potrebbero far sì che i tuoi contenuti vengano pubblicati su più URL (qualcosa che Google penalizza e causerà la divisione del PageRank tra di loro):

  • URL senza distinzione tra maiuscole e minuscole
  • URL predefinito

Puoi impostare il controller / azione predefinito da pubblicare per le richieste alla radice del tuo dominio. Diciamo che scegliamo HomeController / Index. Finiamo con i seguenti URL che offrono lo stesso contenuto:

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

Ora, se le persone iniziano a collegarsi a entrambi, il PageRank verrebbe diviso. Google considererebbe anche i suoi contenuti duplicati e penalizzerebbe uno di loro per evitare duplicati nei loro risultati.

Inoltre, gli URL non fanno distinzione tra maiuscole e minuscole, quindi in realtà otteniamo lo stesso contenuto anche per questi URL:

  • mydomain.com/Home/Index
  • mydomain.com/home/index
  • mydomain.com/Home/index
  • mydomain.com/home/Index
  • (l'elenco continua)

Quindi, la domanda ... Come posso evitare queste penalità? Vorrei:

  • Tutte le richieste di reindirizzamento dell'azione predefinita (stato 301) allo stesso URL
  • Tutti gli URL devono essere case sensitive

Possibile?

È stato utile?

Soluzione

Bump!

MVC 5 Ora supporta la produzione di solo URL minuscoli e criteri comuni per la barra rovesciata.

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

Anche sulla mia applicazione per evitare contenuti duplicati su diversi domini / involucri Ip / Letter ecc ...

  

http://yourdomain.com/en

     

https://yourClientIdAt.YourHostingPacket.com/

Tendo a produrre URL canonici basati su un PrimaryDomain - Protocollo - Controller - Lingua - Azione

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

Quindi puoi utilizzare la risposta di @Gabe Sumner per reindirizzare all'URL canonico della tua azione se l'URL della richiesta corrente non corrisponde.

Altri suggerimenti

Ci stavo lavorando anche su questo. Ovviamente, rimanderò a ScottGu. Offro umilmente anche la mia soluzione a questo problema.

Aggiungi il seguente codice a 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();
    }
}

Un'ottima domanda!

Oltre a pubblicare qui, ho inviato un'e-mail a ScottGu per vedere se aveva una buona risposta. Ha fornito un esempio per l'aggiunta di vincoli ai percorsi, in modo da poter rispondere solo agli URL minuscoli:

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

E nel metodo delle rotte di registro:

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

È un inizio, ma vorrei poter cambiare la generazione di collegamenti da metodi come Html.ActionLink e RedirectToAction in modo che corrispondano.

Credo che ci sia una risposta migliore a questo. Se inserisci un link canonico nella testa della tua pagina come:

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

Quindi google mostra solo la pagina canonica nei loro risultati e, soprattutto, tutta la bontà di google va a quella pagina senza penalità.

Come te, ho avuto la stessa domanda ; tranne che non ero disposto ad accontentarmi di una limitazione dell'URL tutto in minuscolo, e non mi piaceva neanche l'approccio canonico (beh, è ??buono ma non da solo).

Non sono riuscito a trovare una soluzione, quindi abbiamo scritto e aperto a classe di reindirizzamento .

Usarlo è abbastanza semplice: ogni metodo GET nelle classi del controller deve aggiungere solo questa riga all'inizio:

Seo.SeoRedirect(this);

La classe di riscrittura SEO utilizza automaticamente gli attributi Informazioni sul chiamante di C # 5.0 per eseguire il lavoro pesante, rendendo il codice sopra rigorosamente copia-e-incolla.

Come menziono nel SO Q & amp; A collegato, sto lavorando a un modo per convertirlo in un attributo, ma per ora, fa il lavoro.

Il codice forzerà un caso per l'URL. Il caso sarà lo stesso del nome del metodo del controller: scegli se vuoi tutti i limiti, tutti più bassi o un mix di entrambi (CamelCase è buono per gli URL). Emetterà 301 reindirizzamenti per corrispondenze senza distinzione tra maiuscole e minuscole e memorizza nella cache i risultati per ottenere le migliori prestazioni. Reindirizzerà anche le barre rovesciate finali (applicate per elenchi di indici, applicate diversamente) e rimuoverà i contenuti duplicati a cui si accede tramite il nome del metodo predefinito ( Index in un'app ASP.NET MVC stock).

Non so davvero come ti sentirai dopo 8 anni, ma ora ASP MVC 5 supporta il routing degli attributi per percorsi facili da ricordare e la risoluzione di problemi di contenuti duplicati per i siti SEO Friendly

basta aggiungere routes.MapMvcAttributeRoutes (); nel tuo RouteConfig e poi definisci un unico percorso per ogni azione come

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

Basato sulla risposta di Gabe Sumner, ma senza reindirizzamenti per JS, immagini e altri contenuti. Funziona solo su azioni del controller. L'idea è di effettuare il reindirizzamento più avanti nella pipeline quando sappiamo già che è un percorso. Per questo possiamo usare 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);
    }
}

Nota che il filtro sopra non reindirizza o modifica il case per la stringa di query.

Quindi associa ActionFilter a livello globale a tutte le azioni aggiungendolo a GlobalFilterCollection.

filters.Add(new RedirectFilterAttribute());

È una buona idea impostare ancora la proprietà LowercaseUrls su true su RouteCollection.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top