1

I am using asp net core mvc and trying to develop a RESTful app. Let's say I have models like this:

internal class Album 
{       
    public long Id { get; set; }
    public string Name { get; set; }
    public long ExecutorId { get; set; }
    public virtual Executor Executor { get; set; }
}


internal class Executor 
{       
    public long Id { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Album> Albums { get; set; }
}

And I have 2 controllers, that I wrote like this:

[ApiVersion("1")]
[Route("api/v{api-version:apiVersion}/[controller]")]
public class ExecutorsController : Controller
{
    [HttpGet("{id}", Name = "GetExecutor")]
    public IActionResult GetById(long id)
    {
        //some code
    }

    [HttpGet(Name = "GetExecutors")]
    public IActionResult GetAll()
    {
        //some code
    }
}

[ApiVersion("1")]
[Route("api/v{api-version:apiVersion}/[controller]")]
public class AlbumController : Controller
{
    [HttpGet("{id}", Name = "GetAlbum")]
    public IActionResult GetById(long id)
    {
        //some code
    }

    [HttpGet(Name = "GetAlbums")]
    public IActionResult GetAll()
    {
        //some code
    }
}

I can call http://localhost:48234/api/v1/Album/1 and get album by Id, I can call http://localhost:48234/api/v1/Album and get all albums. The same thing works with executors. So, what I want to do, is to be able to get albums by executorId and that my route would look like http://localhost:48234/api/v1/executors/1/albums, which will return all albums for executor with Id = 1. The problem is that I would like to put this action into AlbumsController:

[HttpGet]
[Route("executors/{executorId}/albums")]
public IActionResult GetAlbumsByExecutorId(long executorId)
{
    return new ObjectResult(_service.GetAlbumsByExecutorId(executorId));
}

This code works just fine, but it puts ControllerName (Albums) at the beginning. How can I remove ControllerName from my route? Or maybe I shouldn't do this and just put this action to ExecutorsController? I decided to do it like this, because if action returns albums, it should be placed in AlbumsController. Am I wrong?

2 Answers 2

2

Just remove [controller] from route path in controller and move it to the methods.

Something like this:

[ApiVersion("1")]
[Route("api/v{api-version:apiVersion}/")]
public class AlbumController : Controller
{
   [HttpGet("album/{id}", Name = "GetAlbum")]
    public IActionResult GetById(long id)
    {
         //some code
    }

    [HttpGet("album", Name = "GetAlbums")]
    public IActionResult GetAll()
    {
        //some code
    }

    [HttpGet]
    [Route("executors/{executorId}/albums")]
    public IActionResult GetAlbumsByExecutorId(long executorId)
    {
         return new ObjectResult(_service.GetAlbumsByExecutorId(executorId));
    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

It might work with [HttpGet("[controller]/{id}", Name = "GetAlbum")] but i havn't tested that
that's what I did right after your first answer. And it did work perfect.
It works as well on MVC. After I removed "[controller]" from the ActionResult, "asp-controller" is ignored exactly the way I wanted it.
0

If you want to get albums, you should place action method in AlbumController.

I'd like to recommend you this way:

[HttpGet(Name = 'GetAlbumsByExecutorId')]
[Route("{executorId}/albums")]
public IActionResult GetAlbumsByExecutorId(long executorId)
{
    return new ObjectResult(_service.GetAlbumsByExecutorId(executorId));
}

1 Comment

thank you for your response. But the idea is that i want my API to look like www.site.com/api/v1/executors/1/albums

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.