Reputation: 39
I would like to call in browser /api/announce and /api/announce/1. Getting an error with the following Get functions. When I comment out one or the other works, but if I have both functions the GET is not working as expected. Is something wrong with signatures or there is something else?
/api/announce
[HttpGet]
public List<Announcement> GetAnnouncements()
{
Services.Interface.IAnnouncementService service = new Services.Imp.AnnouncementService(_configuration, _logger);
Announcements announcements = service.GetAnnouncements(1, 1);
return announcements;
}
/api/announce/1
[HttpGet]
public ActionResult<Announcement> GetAnnouncements([FromQuery]int ID)
{
Services.Interface.IAnnouncementService service = new Services.Imp.AnnouncementService(_configuration, _logger);
Announcement announcement = service.GetAnnouncement(ID);
return announcement;
}
Upvotes: 0
Views: 1927
Reputation: 969
The signatures are the same for your routing rules, so this exception will be thrown: Microsoft.AspNetCore.Mvc.Internal.AmbiguousActionException: Multiple actions matched.
To make the framework understand which action you want to invoke, you have to be more specific with regards to routing. And if you want to pass the parameter as part of the path, you have to change the [FromQuery]
attribute to [FromRoute]
attribute.
Example:
[HttpGet]
public IActionResult Test()
{
return Ok();
}
[HttpGet("{id}")]
public IActionResult Test([FromRoute]int id)
{
return Ok();
}
Upvotes: 1
Reputation: 4343
This is how I like doing it:
[HttpGet]
[ProducesResponseType(typeof(IList<Currency>), 200)]
public async Task<IActionResult> GetAll()
{
return Ok(await _typeService.GetCurrenciesAsync().ConfigureAwait(false));
}
[HttpGet("{id}", Name = "GetCurrency")]
[ProducesResponseType(typeof(Currency), 200)]
public async Task<IActionResult> Get([FromRoute]int id)
{
return Ok(await _expenseService.GetCurrencyAsync(id).ConfigureAwait(false));
}
We can see in swagger something like this:
/api/Currency
/api/Currency/{id}
Your base controller could be something like this to include a base route:
[Authorize(Policy = Common.Security.Policies.ApiUser)]
[Route("api/[controller]")]
[Benchmark, ApiController]
public abstract class BaseController : ControllerBase
{
protected BaseController()
{ }
}
Here is the controller constructor for completeness:
public class CurrencyController : BaseController
{
private readonly IExpenseEntryService _expenseService;
private readonly ITypeService _typeService;
public CurrencyController(ITypeService typeService, IExpenseEntryService expenseService)
{
_expenseService = expenseService;
_typeService = typeService;
}
Upvotes: 0