MVC 5 và 6 có tùy chọn tạo URL trường hợp thấp hơn cho tuyến đường của bạn. Cấu hình tuyến đường của tôi được hiển thị bên dưới:
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 });
}
}
Với mã này, bạn sẽ không còn cần chuẩn hóa URL vì điều này được thực hiện cho bạn. Một vấn đề có thể xảy ra nếu bạn đang sử dụng URL HTTP và HTTPS và muốn có URL chuẩn cho việc này. Trong trường hợp này, nó khá dễ sử dụng các phương pháp trên và thay thế HTTP bằng HTTPS hoặc ngược lại.
Một vấn đề khác là các trang web bên ngoài liên kết đến trang web của bạn có thể bỏ qua dấu gạch chéo hoặc thêm ký tự chữ hoa và bạn nên thực hiện chuyển hướng vĩnh viễn 301 đến URL chính xác với dấu gạch chéo. Đối với việc sử dụng đầy đủ và mã nguồn, hãy tham khảo blog post tôi và RedirectToCanonicalUrlAttribute
lọc: ví dụ
/// <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
}
Cách sử dụng để đảm bảo tất cả các yêu cầu được 301 chuyển hướng đến URL kinh điển đúng:
filters.Add(new RedirectToCanonicalUrlAttribute(
RouteTable.Routes.AppendTrailingSlash,
RouteTable.Routes.LowercaseUrls));
Tôi đồng ý, cho các trang web mới đó là cách tôi sẽ làm điều đó. Vấn đề là, tôi có một trang web hiện tại tôi đang cố gắng chuyển đổi. –
Tôi có lẽ sẽ không dành quá nhiều thời gian cho nó. Tôi đoán là Google đủ thông minh trong những ngày này để không cho bạn một hit SEO. – Armstrongest