Create canonical URLs including id and title

I want to replicate what StackOverflow does with its URLs.

For instance:

Hidden C # features? - ( Hidden features in C #? )

or

Hidden C # features? - ( Hidden features in C #? )

Let’s take you to the same page, but when they return to the browser, the first one returns.

How do you implement the change to get a larger url?

+1
source share
1 answer

The way I handled this before is to have two routes registered in this order

routes.MapRoute( null, "questions/{id}/{title}", new { controller = "Questions", action = "Index" }, new { id = @"\d+", title = @"[\w\-]*" }); routes.MapRoute( null, "questions/{id}", new { controller = "Questions", action = "Index" }, new { id = @"\d+" }); 

now in the action of the controller,

 public class QuestionsController { private readonly IQuestionRepository _questionRepo; public QuestionsController(IQuestionRepository questionRepo) { _questionRepo = questionRepo; } public ActionResult Index(int id, string title) { var question = _questionRepo.Get(id); if (string.IsNullOrWhiteSpace(title) || title != question.Title.ToSlug()) { return RedirectToAction("Index", new { id, title = question.Title.ToSlug() }).AsMovedPermanently(); } return View(question); } } 

We will constantly redirect the URL containing the header of the header (lowercase header with hyphens as separators) if we only have the identifier. We also verify that the title was correct by checking it against the broken version of the title of the question, thereby creating a canonical URL for the question, which contains both the identifier and the correct pool of headers.

Used by a pair of helpers

 public static class PermanentRedirectionExtensions { public static PermanentRedirectToRouteResult AsMovedPermanently (this RedirectToRouteResult redirection) { return new PermanentRedirectToRouteResult(redirection); } } public class PermanentRedirectToRouteResult : ActionResult { public RedirectToRouteResult Redirection { get; private set; } public PermanentRedirectToRouteResult(RedirectToRouteResult redirection) { this.Redirection = redirection; } public override void ExecuteResult(ControllerContext context) { // After setting up a normal redirection, switch it to a 301 Redirection.ExecuteResult(context); context.HttpContext.Response.StatusCode = 301; context.HttpContext.Response.Status = "301 Moved Permanently"; } } public static class StringExtensions { private static readonly Encoding Encoding = Encoding.GetEncoding("Cyrillic"); public static string RemoveAccent(this string value) { byte[] bytes = Encoding.GetBytes(value); return Encoding.ASCII.GetString(bytes); } public static string ToSlug(this string value) { if (string.IsNullOrWhiteSpace(value)) { return string.Empty; } var str = value.RemoveAccent().ToLowerInvariant(); str = Regex.Replace(str, @"[^a-z0-9\s-]", ""); str = Regex.Replace(str, @"\s+", " ").Trim(); str = str.Substring(0, str.Length <= 200 ? str.Length : 200).Trim(); str = Regex.Replace(str, @"\s", "-"); str = Regex.Replace(str, @"-+", "-"); return str; } } 
+4
source

Source: https://habr.com/ru/post/949179/


All Articles