Mvc: Support 'defaults' with [action] syntax for attribute routes

Created on 8 Oct 2015  路  19Comments  路  Source: aspnet/Mvc

We built a lovely feature to do token replacement on attribute route templates. This will end up generating routes like the following:

[Route("[controller]/[action]/{id?}")]
public class HomeController
{
    // Equivalent to [Route("Home/Index/{id?}")]
    public IActionResult Index()
    {
    }

    // Equivalent to [Route("Home/About/{id?}")]
    public IActionResult About()
    {
    }
}

The suggestion is that we allow 'defaults' in these tokens like this:

[Route("[controller]/[action=Index]/{id?}")]
public class HomeController
{
    // Equivalent to [Route("Home")]
    // Equivalent to [Route("Home/Index/{id?}")]
    public IActionResult Index()
    {
    }

    // Equivalent to [Route("Home/About/{id?}")]
    public IActionResult About()
    {
    }
}
1 - Ready 3 - Optional enhancement

Most helpful comment

Just a reminder - I still like this idea.

All 19 comments

Very nice. So after that no need to register for default routes in startup.cs I guess!!

@NeelBhatt - these are alternatives, and many people prefer one or the other for their own reasons :+1:

Using attribute routes gives you more precise controller over the URL space, but is often more verbose and usually means putting attributes in your controller classes which some people don't like for code-organization reasons.

Using conventional routes (in startup code) is terse and broad and is the way most old school MVC users are used to doing it.

This change is a suggestion to bring some of the terseness of the 'conventional route' way for a pretty common usage pattern.

Okay I got your point and you explained it very nicely :+1: I have used both previously and I prefer attribute routing as per my experience. But as you said, it totally depends on people's preference.

This doesn't look quite right to me. An entire segment is never omitted from the route. I think that if anything, the attribute route behavior for defaults should be:

``` c#
[Route("[controller]/[action=Index]/{id?}")]
public class HomeController
{
// Equivalent to [Route("Home")] - if the "action" segment is omitted, all subsequent segments must be omitted
// Equivalent to [Route("Home/Index/{id?}")]
public IActionResult Index()
{
}

// Equivalent to [Route("Home/About/{id?}")]
public IActionResult About()
{
}

}

However, I think that though this behavior would make sense, it's perhaps not super useful because you can achieve 99% of that by declaring this attribute route:

``` c#
[Route("[controller]/{action=Index}/{id?}")] // 'action' is a regular parameter
public class HomeController
{
    ...
}

The only thing that's different about this compared to my previous example is that it would allow _any_ action value, so you'd have to constrain it to Index|About|Contact|....

But, having said that, I'm not sure how useful this feature is...

it's perhaps not super useful because you can achieve 99% of that by declaring this attribute route

This is explicitly not allowed. You can't use any action-selection tokens ({contoller}, {action}) as parameters in an attribute route. The reason that you mentioned is the reason why it's not allowed :laughing:

Ah, well, then nix that :smile:

But we still have different ideas about what the behavior should be regarding omitted sections. Let's chat tomorrow if it's not clear.

But we still have different ideas about what the behavior should be regarding omitted sections. Let's chat tomorrow if it's not clear.

That was a mistake, I corrected it in my sample.

Oh, great, because @danroth27 and I were freaking out about that :smile: Well, @danroth27 was being rather patient and _I_ was freaking out! :laughing: Not only that, but all the rest of my diatribe no longer makes any sense :trollface:

So, yeah, now that we all agree about what the feature even is, it's certainly an interesting one.

You should visit Arizona. It's relaxing. :cactus: :cactus: :cactus: :cactus: :cactus: :cactus: :cactus: :cactus:

That sounds like a thorny situation.

This is funny! :) The only real mistake is the one from which we learn nothing. ;)

Moving to backlog.

Just a reminder - I still like this idea.

It's been about 11 months since I last bumped this thread. This item is elegant and cool and I think we should do it.

I still like this idea :)

+1 This is not only a nice idea, but I think it is essential. I see not elegant way to define a default route for rest api like this where index is a default route for this particular controller. Note that there will also be other view controllers that does not start with the api prefix

```c#
[Route("api/[controller]/[action]")]
public class MenuController : Controller
{
IMenuBuilder _menuBuilder;
public MenuController(IMenuBuilder menuBuilder)
{
_menuBuilder = menuBuilder;
}

[HttpGet("")]
public MainMenu Index()
{
    var mainMenu=_menuBuilder.GetMenu();
    return mainMenu;
}

```

@rynowak, will this be a good fit for 2.2?

IMO this is a p3 for dispatcher. If we get an chance to do it, then that would be awesome - but I can't imagine us cutting other work to make this fit.

I don't really want to close this because the workarounds for not having this feature are really annoying and error prone. We have gotten feedback about this several times.

@JamesNK, seems like another issue to be handled as part of the dispatcher work. Will you create a new issue in the routing repo, or just move this one?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

miroslavsiska picture miroslavsiska  路  4Comments

rynowak picture rynowak  路  3Comments

workmonitored picture workmonitored  路  3Comments

MariovanZeist picture MariovanZeist  路  4Comments

nefcanto picture nefcanto  路  3Comments