Como posso evitar conteúdo duplicado em ASP.NET MVC devido a URLs e padrões maiúsculas e minúsculas?

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

  •  05-07-2019
  •  | 
  •  

Pergunta

Editar : Agora eu preciso para resolver este problema de verdade, eu fiz um pouco mais investigação e veio com um número de coisas para reduzir duplicado conteúdo. Eu postei código detalhado amostras no meu blog: Reduzir Conteúdo duplicado com ASP.NET MVC

Primeiro post - ir fácil se eu tivesse marcado este erro para cima ou marcado a mal: P

novo quadro ASP.NET MVC do Em Microsoft parece que há duas coisas que podem causar o seu conteúdo para ser servido acima em vários URLs (algo que o Google penalizar por e fará com que seu PageRank para ser dividido entre eles):

    URLs
  • case-insensitive
  • URL padrão

Você pode definir o padrão de controle / ação para servir-se de pedidos para a raiz do seu domínio. Digamos que escolher HomeController / Index. Vamos acabar com os seguintes URLs que servem o mesmo conteúdo:

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

Agora, se as pessoas começam a ligar para ambos, em seguida, PageRank seria dividida. Google considera igualmente conteúdo duplicado e penalizar um deles para duplicatas evitar em seus resultados.

Além disso, as URLs não são case sensitive, então nós realmente obter o mesmo conteúdo para esses URLs demasiado:

  • mydomain.com/Home/Index
  • mydomain.com/home/index
  • mydomain.com/Home/index
  • mydomain.com/home/Index
  • (a lista continua)

Assim, a pergunta ... Como posso evitar essas sanções? Eu gostaria:

  • Todas as solicitações para a ação padrão para ser redirecionado (301 status) para o mesmo url
  • Todas as URLs para ser maiúsculas de minúsculas

Possível?

Foi útil?

Solução

Bump!

MVC 5 agora suporta a produção de urls apenas letras minúsculas e política de barra invertida comum.

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

Também na minha aplicação para evitar conteúdo duplicado em Carta Carcaça diferentes domínios / Ip / etc ...

http://yourdomain.com/en

https://yourClientIdAt.YourHostingPacket.com/

I tendem a produzir Canonical URLs com base em um PrimaryDomain - Protocol - Controlador - Idioma - 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);
}

Então você pode usar A resposta de @Gabe Sumner para redirecionar para url canônica da sua acção, se a corrente url pedido não combiná-lo.

Outras dicas

Eu estava trabalhando neste também. Eu, obviamente, adiar para ScottGu sobre este assunto. Eu humildemente ofereço a minha solução para este problema, bem embora.

Adicione o seguinte código para 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();
    }
}

A grande questão!

Além de postar aqui, eu enviada ScottGu para ver se ele tinha uma boa resposta. Ele deu um exemplo para adicionar restrições para rotas, para que só poderia responder para minúsculas urls:

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 no método de rotas de 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() }
    );
}

É um começo, mas 'd quero ser capaz de mudar a geração de links de métodos como Html.ActionLink e RedirectToAction para corresponder.

Eu acredito que há uma resposta melhor para isso. Se você colocar um link canônico em sua cabeça página como:

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

Então só o Google mostra a página canônica em seus resultados e, mais importante todo o google bondade vai para essa página com nenhuma penalidade.

Como você, tive a mesma pergunta ; Só que eu não estava disposto a se contentar com uma limitação de URL all-minúsculas, e não gostou da abordagem canonical quer (bem, é bom, mas não por conta própria).

Eu não poderia encontrar uma solução, por isso escreveu e open-source um redirecionamento classe .

Usá-lo é bastante fácil: cada método GET nas necessidades classes do controlador para adicionar apenas esta linha no início:

Seo.SeoRedirect(this);

A classe SEO reescrita automaticamente usa C # 5.0 da Info Caller atributos para fazer o trabalho pesado, tornando o código acima estritamente copiar-e-colar.

Como eu mencionei no ligada SO Q & A, eu estou trabalhando em uma maneira de obter essa convertido para um atributo, mas por agora, ele começa o trabalho feito.

O código irá forçar um caso para o URL. O caso será o mesmo que o nome do método do controlador - você escolher se você quer todas as tampas, todos inferior, ou uma mistura de ambos (CamelCase é bom para URLs). Ele vai emitir 301 redirecionamentos para partidas maiúsculas e minúsculas, e armazena em cache os resultados na memória para melhor desempenho. Ele também vai redirecionar arrastando as barras invertidas (imposta por listas de índice, executada fora de outra forma) e remover conteúdo duplicado acessado através do nome do método padrão (Index em um aplicativo de estoque ASP.NET MVC).

Eu realmente não sei como você vai se sentir depois de 8 anos, mas agora ASP MVC 5 suporta o atributo roteamento para fácil de lembrar rotas e resolvidos problemas de conteúdo duplicado para os sites SEO amigável

Basta adicionar routes.MapMvcAttributeRoutes (); em sua RouteConfig e, em seguida, definir uma e única rota para cada ação como

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

Com base na resposta do Gabe Sumner, mas sem redirecionamentos para JS, imagens e outros conteúdos. Só funciona em ações do controlador. A idéia é fazer o redirecionamento no final do gasoduto quando já sabemos a sua rota a. Para isso, pode usar um 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);
    }
}

Note que o filtro acima não redirecionar ou alterar o invólucro para a string de consulta.

Em seguida, ligam o ActionFilter globalmente para todas as ações por adicioná-lo ao GlobalFilterCollection.

filters.Add(new RedirectFilterAttribute());

É uma boa idéia para ainda definir a propriedade LowercaseUrls a verdade sobre o RouteCollection.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top