1
votes

I've added an ApiController to my asp.net core 2.2 app and the async calls from the UI are not matching.

Here are my routes in Startup.cs.

app.UseMvc(config =>
{
    config.MapRoute(
        "Api",
        "api/{controller}/{action}/{id?}"
    );

    config.MapRoute(
        "Default", 
        "{controller=App}/{action=Index}/{id?}"
    );
});

Here is one of the javascript functions that's making various GET requests to the API controller.

function clearAllFilters() {
  $.get({
    url: "/api/GridFilter/ClearAllFilters",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function () {
        console.log('filters cleared');
    }
  });
}

Here is the API controller:

[Route("api/[controller]")]
[ApiController]
public class GridFilterController : ControllerBase
{
    private static readonly string[] FilterFields = {
        // Bunch of strings, omitted for brevity
    };

    [HttpGet]
    public IActionResult ClearAllFilters()
    {
        foreach (string column in FilterFields)
        {
            if (HttpContext.Session.TryGetValue(column, out byte[] savedJson))
            {
                HttpContext.Session.Remove(column);
            }
        }
        return Ok(true);
    }

Why doesn't asp.net match this? My url is /api/controller/action which seems like it matches the first route that's mapped in startup.

1

1 Answers

1
votes

You're mixing Conventional Routing and Attribute Routing:

Actions are either conventionally routed or attribute routed. Placing a route on the controller or the action makes it attribute routed. Actions that define attribute routes cannot be reached through the conventional routes and vice-versa. Any route attribute on the controller makes all actions in the controller attribute routed.

The following call from your example configures a conventional routing template:

config.MapRoute("Api","api/{controller}/{action}/{id?}");

However, you've configured GridFilterController to use attribute routing by using a routing attribute ([Route(...)]):

[Route("api/[controller]")]
[ApiController]
public class GridFilterController : ControllerBase

To access the ClearAllFilters action from /api/GridFilter/ClearAllFilters, you have two general options:

  1. Change the attribute routing template to:

    [Route("api/[controller]/[action]")]
    

    This means the name of the action will be included as part of the route, which is similar to the conventional routing template you've set up.

  2. Remove the [Route(...)] attribute altogether. However, this isn't ideal, as you'll also have to remove the [ApiController] attribute because that requires attribute routing.