36

I am working on an asp.net 5 mvc api, and I am currently working on the Accounts Controller.

since I saw in many different places that there is a convention of using /api/Tokenrouting to a login in a web api. I would like to route to that specific method without the accounts prefix, I would prefer not using a different controller, and I would prefer using Attributes over routing in Startup.cs to avoid confusion in the future.

this is what I have currently

[Route("api/[controller]")]
public class AccountsController : Controller
{
    [HttpPost("login")]
    public async Task<JwtToken> Token([FromBody]Credentials credentials)
    {
     ...
    }

    [HttpPost]
    public async Task CreateUser([FromBody] userDto)
    {
      ...
    }
}

3 Answers 3

75

With attribute routing you can use a tilde (~) on the Action's route attribute to override the default route of the Controller if needed:

[Route("api/[controller]")]
public class AccountsController : Controller {

    [HttpPost]
    [Route("~/api/token")] //routes to `/api/token`
    public async Task<JwtToken> Token([FromBody]Credentials credentials) {
        ...
    }

    [HttpPost] 
    [Route("users")] // routes to `/api/accounts/users`
    public async Task CreateUser([FromBody] userDto) {
        ...
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Just to highlight something for @gilmishal, you can have a Route attribute on the Actions, as well as on the Controller.
I edited the answer to reflect that. Should I highlight that in the answer as well?
Just for the sake of it, maybe do an example where it actually overrides the route? Right now they're both using /api/.
While they both use /api/ the routes are different in that the original would be /api/accounts/login while the overridden example I suggested goes to /api/token like the OP wanted.
For views (not api) see stackoverflow.com/a/15836469/9258504
49

For ASP.NET Core it seems that the tilde ~ symbol (see accepted answer) is not needed anymore to override the controller's route prefix – instead, the following rule applies:

Route templates applied to an action that begin with a / don't get combined with route templates applied to the controller. This example matches a set of URL paths similar to the default route.

Here is an example:

[Route("foo")]
public class FooController : Controller
{
    [Route("bar")] // combined with "foo" to map to route "/foo/bar"
    public IActionResult Bar()
    {
        // ...
    }

    [Route("/hello/world")] // not combined; maps to route "/hello/world"
    public IActionResult HelloWorld()
    {

    }   
}

1 Comment

This is handy to know. However, I think it's still useful to add the tilde as it makes it more obvious that, for that action, the route will not include the controller's route prefix. The difference between action routes of hello/world and /hello/world is fairly subtle, whereas ~/hello/world stands out more.
2

from https://learn.microsoft.com/en-us/aspnet/core/mvc/controllers/routing

[Route("[controller]/[action]")]
public class HomeController : Controller
{
    [Route("~/")]
    [Route("/Home")]
    [Route("~/Home/Index")]
    public IActionResult Index()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }

    public IActionResult About()
    {
        return ControllerContext.MyDisplayRouteInfo();
    }
}

In the preceding code, the Index method templates must prepend / or ~/ to the route templates. Route templates applied to an action that begin with / or ~/ don't get combined with route templates applied to the controller.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.