I'm trying to get a REST service up and running (I followed this tutorial), and was trying to extend it with a simple method to mark one of the ToDoItem as "Complete"; literally to pass an ID into a method which should mark it as "Complete".
However, I'm struggling to understand how the routing works.
This is the method provided by default, which works correctly via https://localhost:44388/api/values
If I add another GET operation, even with different [Route] attribute, then I end up with "AmbiguousActionException: Multiple actions matched"
[Route("api/values")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
I tried to specify a route prefix using the method below, so that I could add doesn't work; I get a 404 on https://localhost:44388/api/values and https://localhost:44388/api/values/getbyname
[RoutePrefix("api/values")]
[ApiController]
public class ValuesController : ControllerBase
{
// GET api/values
[Route("getbyname")]
[HttpGet]
public ActionResult<IEnumerable<string>> Get()
{
return new string[] { "value1", "value2" };
}
I might be trying the wrong method, so I'm happy to take any advice. I just want to be able to create new REST calls and have them the appropriate actions. Do I need to create other controllers? Am I limited to one GET/POST/PUT etc per controller?
Edit: didn't provide enough info, here's more code:
[Route("api/ToDo")]
[ApiController]
public class ToDoController : ControllerBase
{
private readonly ToDoContext _context;
public ToDoController(ToDoContext toDoContext)
{
_context = toDoContext;
if (_context.ToDoItems.Count() == 0)
{
//collection is empty, so add a new item
ToDoItem item1 = new ToDoItem(1, "example 1");
ToDoItem item2 = new ToDoItem(2, "example 2");
_context.ToDoItems.Add(item1);
_context.ToDoItems.Add(item2);
_context.SaveChanges();
}
}
//GET: api/todo
[HttpGet]
public async Task<ActionResult<IEnumerable<ToDoItem>>> GetToDoItems()
{
return await _context.ToDoItems.ToListAsync();
}
//GET: api/todo/5
//[HttpGet(Name = "Get a ToDoItem")]
//[Route("get{id}")]
[HttpGet("{id}")]
public async Task<ActionResult<ToDoItem>> GetToDoItem(long id)
{
var todoitem = await _context.ToDoItems.FindAsync(id);
if (todoitem == null)
{
return NotFound();
}
return todoitem;
}
//POST: api/Todo
[HttpPost]
public async Task<ActionResult<ToDoItem>> PostToDoItem(ToDoItem todoItem)
{
_context.ToDoItems.Add(todoItem);
await _context.SaveChangesAsync();
//calls the "GetToDoItem" method above!
return CreatedAtAction("GetToDoItem", new { id = todoItem.ID }, todoItem);
}
//DELETE: api/todo/5
[HttpDelete("{id}")]
public async Task<ActionResult<ToDoItem>> DeleteToDoItem(long id)
{
var todoItem = await _context.ToDoItems.FindAsync(id);
if(todoItem == null)
{
return NotFound();
}
_context.ToDoItems.Remove(todoItem);
await _context.SaveChangesAsync();
return todoItem;
}
//* -. space to create a "MarkAsComplete" method
//GET: api/todo/5
[HttpGet(Name = "{name}")]
public async Task<ActionResult<ToDoItem>> MarkAsComplete(long id)
{
var todoitem = await _context.ToDoItems.FindAsync(id);
if (todoitem == null)
{
return NotFound();
}
else
{
todoitem.IsComplete = true;
}
return todoitem;
}
//*/
}