5

Can we use dashes (-) in the Route template in ASP.NET Core?

// GET: api/customers/5/orders?active-orders=true
[Route("customers/{customer-id}/orders")]
public IActionResult GetCustomerOrders(int customerId, bool activeOrders)
{
    .
    .
    .
}

(The above code doesn't work)

Tohid
  • 6,175
  • 7
  • 51
  • 80
  • but why do you want to do that? – Aman B Oct 27 '18 at 14:49
  • Yea, good question. Why would you want do that in the first place? the route parameters usually directly map to the variable name, so `Route("customers/{customerid}/orders")` should work since thats the name of your variable. However, you can try `public IActionResult GetCustomerOrders([FromRoute(Name = "customer-id")]int customerId, bool activeOrders)` – Tseng Oct 27 '18 at 15:30
  • @Tseng - 1. "We recommend that you use hyphens (-) instead of underscores (_) in your URLs." https://support.google.com/webmasters/answer/76329?hl=en 2. I tried your solution and it works. I also can have `..., [FromQuery(Name = "active-orders")] bool activeOrders)`. Super. Problem solved. Could you please post these 2 comments as an answer for the sake of others? – Tohid Oct 28 '18 at 00:52
  • @AmanB - It is recommended to use dashes instead of camelCase or hyphen in a URL. See: https://stackoverflow.com/a/2318376/538387 – Tohid Oct 28 '18 at 00:59
  • @AmanB as a designer I think it looks much better, and the url is something the customer sees – quemeful May 20 '19 at 12:15

2 Answers2

9

The route parameters usually directly map to the action's variable name, so [Route("customers/{customerId}/orders")] should work since that's the name of your variable (int customerId).

You don't need dashes there, the part within the curly braces {} will never appear as a part of the generated url, it will always be replaced by the content you pass from browser or the variables you pass to the url generator.

customers/{customerId}/orders will always be customers/1/orders when customerId is set to 1, so there's no point trying to force it to {customer-id}.

However, you can try public

[Route("customers/{customer-id}/orders")]
IActionResult GetCustomerOrders([FromRoute(Name = "customer-id")]int customerId, bool activeOrders)

to bind the customerId from a unconventional route name, if you wish. But I'd strongly advise against it, as it just adds unnecessary code which has absolutely zero-effect on your generated urls.

The above generates (and parses) the exactly same url as

[Route("customers/{customerId}/orders")]
IActionResult GetCustomerOrders(int customerId, bool activeOrders)

and is much more readable code.

For the query part, as you figured it out in the comments, it makes sense to add the dashes via [FromQuery(Name = "active-orders")] bool activeOrders, since that really affects the generated url.

New in ASP.NET Core 2.2

In ASP.NET Core 2.2 you'll get a new option to 'slugify' your routes (only supported when using the new Route Dispatcher instead of the default Mvc Router).

A route of blog\{article:slugify} will (when used with Url.Action(new { article = "MyTestArticle" })) generate blog\my-test-article as url.

Can also be used in default routes:

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

For further details see the ASP.NET Core 2.2-preview 3 annoucement.

Community
  • 1
  • 1
Tseng
  • 61,549
  • 15
  • 193
  • 205
1

Just expanding on Tseng answer to the question. for ASP NET CORE to use "slugify" transformer you need to register it first like so:

public class SlugifyParameterTransformer : IOutboundParameterTransformer
{
    public string TransformOutbound(object value)
    {
        if (value == null) { return null; }

        return Regex.Replace(value.ToString(), 
                             "([a-z])([A-Z])",
                             "$1-$2",
                             RegexOptions.CultureInvariant,
                             TimeSpan.FromMilliseconds(100)).ToLowerInvariant();
    }
}

and then in Startup.cs

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();

    services.AddRouting(options =>
    {
        options.ConstraintMap["slugify"] = typeof(SlugifyParameterTransformer);
    });
}

Code from Microsoft

Hamed
  • 356
  • 2
  • 9