How to Create a Friendly Url in ASP.NET MVC

How can I create a friendly URL in ASP.NET MVC?

There are two steps to solve this problem. First, create a new route or change the default route to accept an additional parameter:

routes.MapRoute(  "Default", // Route name
"{controller}/{action}/{id}/{ignoreThisBit}",
new { controller = "Home",
action = "Index",
id = "",
ignoreThisBit = ""} // Parameter defaults )

Now you can type whatever you want to at the end of your URI and the application will ignore it.

When you render the links, you need to add the "friendly" text:

<%= Html.ActionLink("Link text", "ActionName", "ControllerName",
new { id = 1234, ignoreThisBit="friendly-text-here" });

Asp.net MVC SEO Friendly URL

Please try with below solution. In global.asax.cs

routes.MapRoute(
"Product",
"{productName}",
new { controller = "Product", action = "Index" },
new { productName = UrlParameter.Optional }
);

But you required to maintain uniqueness in productName and fetch record by that in index action of product controller (i.e in product Controller:

public ActionResult index(string productName)
{
//do something regarding get product by productname
}

ASP.NET Mvc 5 return View with seo friendly url

You will have to look in the database for the SEO friendly slug before redirecting and include it in the url, otherwise it's too late:

[HttpPost]
[AllowAnonymous]
[Route("Cat/SelCat/{form?}")]
public ActionResult SelCat(FormCollection form)
{
string selectedValues = form["SelectedCat"];
// ...
int id = selectedCatID;

// look in the database for title by the given id
string seofriendlyTitle = ...;
return RedirectToAction("Index", new { id = id, seoname = seofriendlyTitle });
}

Once you have reached the Index action it is already too late to be able to alter the url that is shown on the client, unless you make an additional redirect (which of course would be insane).

Helper to generate friendly URL in Razor (C#/MVC 4)

I've done this before. While I dig up the code, here are things to keep in consideration:

  1. Make sure you store your generated URLs so you can do collision detection; converting strings to friendly URLs is almost certainly going to be lossy, so you need logic to resolve conflicted names.
  2. You ought to try to convert diacritical marks into more easily-typable characters.
  3. Consider making url-to-resource mappings a 1:many relationship; if the name of your resource changes, you may want to generate a new URL and have the old URL redirect to the new.

UPDATE: Here is my code for this. The Stack Overflow approach is OK, but I like mine better; instead of using a set of character substitutions, it uses the great .NET Unicode library to create friendlier characters:

public static string ConvertToFriendlyUrl(string text)
{
var decomposed = text.Normalize(NormalizationForm.FormKD);
var builder = new StringBuilder();
foreach (var ch in decomposed)
{
var charInfo = CharUnicodeInfo.GetUnicodeCategory(ch);
switch (charInfo)
{
// Keep these as they are
case UnicodeCategory.DecimalDigitNumber:
case UnicodeCategory.LetterNumber:
case UnicodeCategory.LowercaseLetter:
case UnicodeCategory.CurrencySymbol:
case UnicodeCategory.OtherLetter:
case UnicodeCategory.OtherNumber:
builder.Append(ch);
break;

// Convert these to dashes
case UnicodeCategory.DashPunctuation:
case UnicodeCategory.MathSymbol:
case UnicodeCategory.ModifierSymbol:
case UnicodeCategory.OtherPunctuation:
case UnicodeCategory.OtherSymbol:
case UnicodeCategory.SpaceSeparator:
builder.Append('-');
break;

// Convert to lower-case
case UnicodeCategory.TitlecaseLetter:
case UnicodeCategory.UppercaseLetter:
builder.Append(char.ToLowerInvariant(ch));
break;

// Ignore certain types of characters
case UnicodeCategory.OpenPunctuation:
case UnicodeCategory.ClosePunctuation:
case UnicodeCategory.ConnectorPunctuation:
case UnicodeCategory.Control:
case UnicodeCategory.EnclosingMark:
case UnicodeCategory.FinalQuotePunctuation:
case UnicodeCategory.Format:
case UnicodeCategory.InitialQuotePunctuation:
case UnicodeCategory.LineSeparator:
case UnicodeCategory.ModifierLetter:
case UnicodeCategory.NonSpacingMark:
case UnicodeCategory.OtherNotAssigned:
case UnicodeCategory.ParagraphSeparator:
case UnicodeCategory.PrivateUse:
case UnicodeCategory.SpacingCombiningMark:
case UnicodeCategory.Surrogate:
break;
}
}

var built = builder.ToString();
while (built.Contains("--"))
built = built.Replace("--", "-");
while (built.EndsWith("-"))
{
built = built.Substring(0, built.Length - 1);
}
while (built.StartsWith("-"))
{
built = built.Substring(1, built.Length - 1);
}
return built;
}

public static string GetIncrementedUrl(string url)
{
var parts = url.Split('-');
var lastPortion = parts.LastOrDefault();
int numToInc;
bool incExisting;
if (lastPortion == null)
{
numToInc = 1;
incExisting = false;
}
else
{
if (int.TryParse(lastPortion, out numToInc))
{
incExisting = true;
}
else
{
incExisting = false;
numToInc = 1;
}
}

var fragToKeep = incExisting
? string.Join("-", parts.Take(parts.Length - 1).ToArray())
: url;
return fragToKeep + "-" + (numToInc + 1).ToString();
}

public static string SeekUrl(
string name, Func<string, bool> uniquenessCheck)
{
var urlName = UrlUtils.ConvertToFriendlyUrl(name);
while (!uniquenessCheck(urlName))
{
urlName = UrlUtils.GetIncrementedUrl(urlName);
}

return urlName;
}

How to show seo friendly url in mvc core 3.1?

First off, URIs need to be resilient. You say your current requirement is to have URIs like this:

www.abc.com/alivia-black

i.e.:

{host}/{productName}

That's a very bad URI template because:

  • It does not uniquely identify the product (as you could have multiple products with the same name).
  • It will break existing links from external websites if you ever rename a product or replace a product with the same name. And this happens a lot in any product database.
  • Because you're putting the {productName} in the "root" of your URI structure it means it's much harder to handle anything else besides viewing products (e.g. how would you have a /contact-us page? What if you had a product that was named contact-us?)

I stress that is is very important to include an immutable key to the entity being requested (in this case, your productId value) in the URI and use that as a primary-reference, so the productName can be ignored when handling an incoming HTTP request. This is how StackOverflow's and Amazon's URIs work (you can trim off the text after a StackOverflow's question-id and it will still work: e.g.

https://stackoverflow.com/questions/69748993/how-to-show-seo-friendly-url-in-mvc-core-3-1

https://stackoverflow.com/questions/69748993

I strongly recommend you read this article on the W3.org's website all about designing good URIs, as well as other guidance from that group's homepage.


I suggest you use a much better URI template, such as this one:

{host}/products/{productId}/{productName}

Which will give you a URI like this:

abc.com/products/5088/alivablack

Handling such a link in ASP.NET MVC (and ASP.NET Core) is trivial, just set the route-template on your controller action:

[Route( "/products/{productId:int}/{productName?}" )]
public async Task<IActionResult> ShowProduct( Int32 productId, String? productName = null )
{
// Use `productId` to lookup the product.
// Disregard `productName` unless you want to use it as a fallback to search your database if `productId` doesn't work.
}

As for generating URIs, as I recommend against using TagHelpers (e.g. <a asp-route-) because they don't give you sufficient control over how the URI is rendered, instead you can define a UrlHelper extension method (ensure you @import the namespace into your .cshtml pages (or add it to ViewStart):

public static class MyUrls
{
public static String ShowProduct( this IUrlHelper u, Int32 productId, String productName )
{
const String ACTION_NAME = nameof(ProductsController.ShowProduct);
const String CONTROLLER_NAME = "Products"; // Unfortunately we can't use `nameof` here due to the "Controller" suffix in the type-name.

String url = u.Action( action: ACTION_NAME, controller: CONTROLLER_NAME, values: new { productId = productId, productName = productName } );
return url;
}
}

Then you can use it like so:

<a href="@Urls.ShowProduct( 5088, "aliviablack" )">View AliviaBlack</a>

You can also make ShowProduct accept one of your Product objects directly and then pass the values on to the other overload (defined above) which accepts scalars:

    public static String ShowProduct( this IUrlHelper u, Product product )
{
String url = ShowProduct( u, productId: product.ProductId, productName: product.ProductName );
return url;
}

Then you can use it like so (assuming product is in-scope):

<a href="@Urls.ShowProduct( product )">@product.ProductName</a>

ASP.NET MVC Routing / SEO Friendly URL

That route looks like it should work with that call to ActionLink, so this is a bit of a guess. Are you registering your {action}/{id}/{title} route after the default route? If so, the default route will match first, and just put the title value in the querystring since it doesn't appear in the path. If you register your custom route before the {controller}/{action}/{id} default, it should work.

Can you produce friendly URLs with an ActionLink?

You can add a MapRoute like this as your last route

        routes.MapRoute(
name: "UrlFriendly",
url: "{*url}",
defaults: new { controller = "UrlFriendly", action = "Index" }
);

If you have a complex website you'll need to handle all cases, and this could be a big amount of work!

How do I create SEO-Friendly urls in ASP.Net-MVC

Create a new route in the Global.asax to handle this:

        routes.MapRoute(
"productId", // Route name
"productId/{id}/{name}", // URL with parameters
new { controller = "Home", action = "productId", id = 1234, name = widget } // Parameter defaults
);

Asp.Net MVC has routing built in, so no need for the Url Rewriter.

Friendly URLs in ASP.NET MVC 6 (ASP.NET Core or ASP.NET5)

To globally configure routing in ASP.NET Core, use extension method in Startup.cs:

 app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});

In your case, for url:

https://www.mywebsite.com/v/56b8b8801561e80c245a165c/amazing-product-name

it could look like this:

 app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "v/{customId}/{customName}",
defaults : new{controller = "View", action = "Index"});
});

And then your action should handle customId and customName parameters as follows:

public IActionResult Index(string customId, string customName)
{
//customId will be 56b8b8801561e80c245a165c
//customName will be amazing-product-name
}

For more info about routing in ASP.NET Core go to:
http://docs.asp.net/en/latest/fundamentals/routing.html?highlight=routing



Related Topics



Leave a reply



Submit