I am using .NET 8.0 in an ASP.NET Core application.
I have a class as follows:
/// Controller for diagram retrieval.
/// </summary>
[Route("api/Projects")]
[ApiController]
[Authorize]
public class ProjectsEndpoints : ControllerBase
{
private IGenesysApiService _apiRequestService;
private AppSettings _appSettings;
public ProjectsEndpoints(IGenesysApiService apiClientService, AppSettings appSettings)
{
_apiRequestService = apiClientService;
_appSettings = appSettings;
}
public async Task<Project> GetProjects()
{
await AddGenesysToken();
var url = _appSettings.GenesysApiURI + "/Projects";
var list = await _apiRequestService.GetAsync<Project>(url);
return list.Body;
}
private async Task AddGenesysToken()
{
var token = await _apiRequestService.GetAccessTokenForUserAsync();
_apiRequestService.RequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", token);
}
}
If i add a function such as:
public async Task<Entity> GetEntitiesByProject(string projectId)
{
try
{
await AddGenesysToken();
var ret = await _apiRequestService.GetAsync<Entity>($"/entities/{projectId}/f5a2162d-74d3-47a0-9b8b-e51d12db78a0");
return ret.Body;
}
catch (Exception ex)
{
return null;
}
}
WHICH I DO NOT EVEN CALL, I get the error below when trying to call getprojects().
If i comment out the unused function, it works fine.
Loaded 12.51 MB resources from cache Debugging hotkey: Shift+Alt+D (when application has focus) CSS Hot Reload ignoring https://localhost:44367/_content/Microsoft.FluentUI.AspNetCore.Components/Microsoft.FluentUI.AspNetCore.Components.bundle.scp.css because it was inaccessible or had more than 5000 rules. Registered: fail: Sidekick.Client.Shared.Services.ApiClientService[0] Server error. fail: Microsoft.AspNetCore.Components.Web.ErrorBoundary[0] System.NullReferenceException: Object reference not set to an instance of an object. at Sidekick.Client.Features.Projects.Services.ProjectsService.GetProjects() in C:\Source\Sidekick\development\Client\Features\Projects\Services\ProjectsService.cs:line 23 at Sidekick.Client.Features.Diagram.ProjectListComponent.OnInitializedAsync() in C:\Source\Sidekick\development\Client\Features\Diagram\ProjectListComponent.razor:line 51 at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync() at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState) System.NullReferenceException: Object reference not set to an instance of an object. at Sidekick.Client.Features.Projects.Services.ProjectsService.GetProjects() in C:\Source\Sidekick\development\Client\Features\Projects\Services\ProjectsService.cs:line 23 at Sidekick.Client.Features.Diagram.ProjectListComponent.OnInitializedAsync() in C:\Source\Sidekick\development\Client\Features\Diagram\ProjectListComponent.razor:line 51 at Microsoft.AspNetCore.Components.ComponentBase.RunInitAndSetParametersAsync() at Microsoft.AspNetCore.Components.RenderTree.Renderer.GetErrorHandledTask(Task taskToHandle, ComponentState owningComponentState)
I validated that get projects works ONLY if i don't add functions to the class. Very strange. Again, the only change i made was to add the functions that i don't yet call to the class.
I am launching in debugger using IIS Express.
Very strange
It actually is not. I highly recommend to check out the Routing to controller actions in ASP.NET Core docs. Basically you have defined a single route for your controller via:
[Route("api/Projects")]
And from the previously linked docs:
Action definition
Public methods on a controller, except those with the
NonAction
attribute, are actions.
So when you add a second method you end up with 2 actions matching the same route, hence if you try calling it directly you will get something like the following:
An unhandled exception occurred while processing the request.
AmbiguousMatchException: The request matched multiple endpoints. Matches:
ProjectsEndpoints.GetProjects (ASPNET8TestApp)
ProjectsEndpoints.GetEntitiesByProject (ASPNET8TestApp)
You can fix it by providing separate route for it, for example:
[Route("api/Projects")]
[ApiController]
public class ProjectsEndpoints : ControllerBase
{
[HttpGet]
public async Task<Project> GetProjects()
{
// ...
}
[HttpGet("{projectId}/entity")]
public async Task<Entity> GetEntitiesByProject(string projectId)
{
// ...
}
}
Which will make GetEntitiesByProject
available at path api/Projects/{someProjIdHere}/entity