What is an SEO friendly url, how to create it?
SEO (Search Engine Optimization) consists of the abbreviation of the words. 90% of most of the traffic to your site comes from search engines such as Google, Bing, Yandex, Yahoo, Yaani etc. In order for people to reach you better, we must comply with the standards set by these engines. Otherwise, we will fall down in the google rankings and you will find yourself in the internet garbage.
SEO is a very comprehensive issue and I will only tell you how to create SEO Friendly Url.
First, let's create a Utils class. No need to explain what the code buffer does in general :) I'll explain how to use it at the bottom.
using System.Globalization;
using System.Text;
namespace Project.Core.Helpers
{
public static class Utils
{
/// <summary>
/// Creates a URL And SEO friendly slug
/// </summary>
/// <param name="text">Text to slugify</param>
/// <param name="maxLength">Max length of slug</param>
/// <returns>URL and SEO friendly string</returns>
public static string PrepareSeoUrl(string text, int maxLength = 0)
{
// Return empty value if text is null
if (text == null) return "";
text = text.Replace("İ", "i");
var normalizedString = text
// Make lowercase
.ToLowerInvariant()
// Normalize the text
.Normalize(NormalizationForm.FormD);
var stringBuilder = new StringBuilder();
var stringLength = normalizedString.Length;
var prevdash = false;
var trueLength = 0;
for (var i = 0; i < stringLength; i++)
{
var c = normalizedString[i];
switch (CharUnicodeInfo.GetUnicodeCategory(c))
{
// Check if the character is a letter or a digit if the character is a
// international character remap it to an ascii valid character
case UnicodeCategory.LowercaseLetter:
case UnicodeCategory.UppercaseLetter:
case UnicodeCategory.DecimalDigitNumber:
if (c < 128)
stringBuilder.Append(c);
else
stringBuilder.Append(RemapInternationalCharToAscii(c));
prevdash = false;
trueLength = stringBuilder.Length;
break;
// Check if the character is to be replaced by a hyphen but only if the last character wasn't
case UnicodeCategory.SpaceSeparator:
case UnicodeCategory.ConnectorPunctuation:
case UnicodeCategory.DashPunctuation:
case UnicodeCategory.OtherPunctuation:
case UnicodeCategory.MathSymbol:
if (!prevdash)
{
stringBuilder.Append('-');
prevdash = true;
trueLength = stringBuilder.Length;
}
break;
}
// If we are at max length, stop parsing
if (maxLength > 0 && trueLength >= maxLength)
break;
}
// Trim excess hyphens
var result = stringBuilder.ToString().Trim('-');
// Remove any excess character to meet maxlength criteria
return maxLength <= 0 || result.Length <= maxLength ? result : result.Substring(0, maxLength);
}
/// <summary>
/// Remaps international characters to ascii compatible ones
/// based of: https://meta.stackexchange.com/questions/7435/non-us-ascii-characters-dropped-from-full-profile-url/7696#7696
/// </summary>
/// <param name="c">Charcter to remap</param>
/// <returns>Remapped character</returns>
private static string RemapInternationalCharToAscii(char c)
{
var s = c.ToString().ToLowerInvariant();
if ("àåáâäãåą".Contains(s))
return "a";
if ("èéêëę".Contains(s))
return "e";
if ("ìíîïı".Contains(s))
return "i";
if ("òóôõöøőð".Contains(s))
return "o";
if ("ùúûüŭů".Contains(s))
return "u";
if ("çćčĉ".Contains(s))
return "c";
if ("żźž".Contains(s))
return "z";
if ("śşšŝ".Contains(s))
return "s";
if ("ñń".Contains(s))
return "n";
if ("ýÿ".Contains(s))
return "y";
if ("ğĝ".Contains(s))
return "g";
return c switch
{
'ř' => "r",
'ł' => "l",
'đ' => "d",
'ß' => "ss",
'þ' => "th",
'ĥ' => "h",
'ĵ' => "j",
_ => ""
};
}
}
}
var blogPost = new BlogPost();
blogPost.Url = Utils.PrepareSeoUrl("New Title", 50);
// blogPost.Url output => new-title
As you can see in the example above, you can convert a text to an SEO Friendly Url. If you add the url with this helper method while writing a url on your listing pages, people will use this url and search engine bots will recognize this url over time and add it to their list.
I'm adding code to guide you on how to capture this url in case you need it.
[Route("blog/{slug}")]
public async Task<IActionResult> Details(string slug)
{
try
{
var model = await db.Table.FirstOrDefaultAsync(_ => _.Url == slug)
return View(model);
}
catch (Exception ex)
{
// TODO add not found page
return RedirectToAction("Index");
}
}