MVC 5 y 6 tiene la opción de generar menor URL caso de para sus rutas. Mi config ruta se muestra a continuación:
public static class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
// Imprive SEO by stopping duplicate URL's due to case or trailing slashes.
routes.AppendTrailingSlash = true;
routes.LowercaseUrls = true;
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });
}
}
Con este código, ya no debería necesitar el canonicalize la URL es como esto se hace para usted. Un problema que puede ocurrir si está utilizando URLs HTTP y HTTPS y quiere una URL canónica para esto. En este caso, es bastante fácil utilizar los enfoques anteriores y reemplazar HTTP con HTTPS o viceversa.
Otro problema es que los sitios web externos que enlazan con su sitio pueden omitir la barra inclinada o agregar caracteres en mayúscula y para esto debe realizar una redirección permanente 301 a la URL correcta con la barra al final. Para el uso completo y el código fuente, consulte mi blog post y el filtro RedirectToCanonicalUrlAttribute
: ejemplo
/// <summary>
/// To improve Search Engine Optimization SEO, there should only be a single URL for each resource. Case
/// differences and/or URL's with/without trailing slashes are treated as different URL's by search engines. This
/// filter redirects all non-canonical URL's based on the settings specified to their canonical equivalent.
/// Note: Non-canonical URL's are not generated by this site template, it is usually external sites which are
/// linking to your site but have changed the URL case or added/removed trailing slashes.
/// (See Google's comments at http://googlewebmastercentral.blogspot.co.uk/2010/04/to-slash-or-not-to-slash.html
/// and Bing's at http://blogs.bing.com/webmaster/2012/01/26/moving-content-think-301-not-relcanonical).
/// </summary>
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)]
public class RedirectToCanonicalUrlAttribute : FilterAttribute, IAuthorizationFilter
{
private readonly bool appendTrailingSlash;
private readonly bool lowercaseUrls;
#region Constructors
/// <summary>
/// Initializes a new instance of the <see cref="RedirectToCanonicalUrlAttribute" /> class.
/// </summary>
/// <param name="appendTrailingSlash">If set to <c>true</c> append trailing slashes, otherwise strip trailing
/// slashes.</param>
/// <param name="lowercaseUrls">If set to <c>true</c> lower-case all URL's.</param>
public RedirectToCanonicalUrlAttribute(
bool appendTrailingSlash,
bool lowercaseUrls)
{
this.appendTrailingSlash = appendTrailingSlash;
this.lowercaseUrls = lowercaseUrls;
}
#endregion
#region Public Methods
/// <summary>
/// Determines whether the HTTP request contains a non-canonical URL using <see cref="TryGetCanonicalUrl"/>,
/// if it doesn't calls the <see cref="HandleNonCanonicalRequest"/> method.
/// </summary>
/// <param name="filterContext">An object that encapsulates information that is required in order to use the
/// <see cref="RedirectToCanonicalUrlAttribute"/> attribute.</param>
/// <exception cref="ArgumentNullException">The <paramref name="filterContext"/> parameter is <c>null</c>.</exception>
public virtual void OnAuthorization(AuthorizationContext filterContext)
{
if (filterContext == null)
{
throw new ArgumentNullException("filterContext");
}
if (string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.Ordinal))
{
string canonicalUrl;
if (!this.TryGetCanonicalUrl(filterContext, out canonicalUrl))
{
this.HandleNonCanonicalRequest(filterContext, canonicalUrl);
}
}
}
#endregion
#region Protected Methods
/// <summary>
/// Determines whether the specified URl is canonical and if it is not, outputs the canonical URL.
/// </summary>
/// <param name="filterContext">An object that encapsulates information that is required in order to use the
/// <see cref="RedirectToCanonicalUrlAttribute" /> attribute.</param>
/// <param name="canonicalUrl">The canonical URL.</param>
/// <returns><c>true</c> if the URL is canonical, otherwise <c>false</c>.</returns>
protected virtual bool TryGetCanonicalUrl(AuthorizationContext filterContext, out string canonicalUrl)
{
bool isCanonical = true;
canonicalUrl = filterContext.HttpContext.Request.Url.ToString();
int queryIndex = canonicalUrl.IndexOf(QueryCharacter);
if (queryIndex == -1)
{
bool hasTrailingSlash = canonicalUrl[canonicalUrl.Length - 1] == SlashCharacter;
if (this.appendTrailingSlash)
{
// Append a trailing slash to the end of the URL.
if (!hasTrailingSlash)
{
canonicalUrl += SlashCharacter;
isCanonical = false;
}
}
else
{
// Trim a trailing slash from the end of the URL.
if (hasTrailingSlash)
{
canonicalUrl = canonicalUrl.TrimEnd(SlashCharacter);
isCanonical = false;
}
}
}
else
{
bool hasTrailingSlash = canonicalUrl[queryIndex - 1] == SlashCharacter;
if (this.appendTrailingSlash)
{
// Append a trailing slash to the end of the URL but before the query string.
if (!hasTrailingSlash)
{
canonicalUrl = canonicalUrl.Insert(queryIndex, SlashCharacter.ToString());
isCanonical = false;
}
}
else
{
// Trim a trailing slash to the end of the URL but before the query string.
if (hasTrailingSlash)
{
canonicalUrl = canonicalUrl.Remove(queryIndex - 1, 1);
isCanonical = false;
}
}
}
if (this.lowercaseUrls)
{
foreach (char character in canonicalUrl)
{
if (char.IsUpper(character))
{
canonicalUrl = canonicalUrl.ToLower();
isCanonical = false;
break;
}
}
}
return isCanonical;
}
/// <summary>
/// Handles HTTP requests for URL's that are not canonical. Performs a 301 Permanent Redirect to the canonical URL.
/// </summary>
/// <param name="filterContext">An object that encapsulates information that is required in order to use the
/// <see cref="RedirectToCanonicalUrlAttribute" /> attribute.</param>
/// <param name="canonicalUrl">The canonical URL.</param>
protected virtual void HandleNonCanonicalRequest(AuthorizationContext filterContext, string canonicalUrl)
{
filterContext.Result = new RedirectResult(canonicalUrl, true);
}
#endregion
}
uso para asegurar que todas las solicitudes son 301 redirigido a la correcta URL canónica:
filters.Add(new RedirectToCanonicalUrlAttribute(
RouteTable.Routes.AppendTrailingSlash,
RouteTable.Routes.LowercaseUrls));
Hay una manera de conseguir en todo el sitio en MVC3 a través de filtros globales, pero en menos de MVC3, deberá crear un controlador base, aplicar el atributo a eso y derivar todos los controladores de él. Sin embargo, tengo que preguntar cuál es el caso de uso para esto. –
SEO. Garantizar que las arañas que entran desde enlaces formateados incorrectamente se redireccionan (permanentemente) al correcto - la carcasa inferior es realmente un lado realmente. http://en.wikipedia.org/wiki/Canonicalization#Search_Engines_and_SEO –