Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to call an action with parameters in .net core?

So I have the following default pattern set in my Startup.cs:

app.UseEndpoints(endpoints =>
{
    endpoints.MapControllerRoute(
        name: "default",
        pattern: "{controller}/{action}/{id?}");
});

And this is my controller:

[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
    private static readonly string[] Summaries = new[]
    {
        "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching"
    };

    private readonly ILogger<WeatherForecastController> _logger;

    public WeatherForecastController(ILogger<WeatherForecastController> logger)
    {
        _logger = logger;
    }

    [HttpGet]
    [Route("[action]")]
    public IEnumerable<WeatherForecast> Get()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 0),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }

    [HttpGet]
    [Route("[action]")]
    public IEnumerable<WeatherForecast> Grab()
    {
        var rng = new Random();
        return Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(1, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }

    [Route("[action]")]
    [HttpGet("{i:int}")]
    public IEnumerable<WeatherForecast> Snatch(int i)
    {
        var rng = new Random();
        return Enumerable.Range(i, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(55, 100),
            Summary = Summaries[rng.Next(Summaries.Length)]
        })
        .ToArray();
    }
}

Now when I call https://localhost:44388/weatherforecast/grab or https://localhost:44388/weatherforecast/get then it works just fine, but if I call https://localhost:44388/weatherforecast/Snatch/1 then I get Error: Cannot match any routes. in my browser.

I've set the last method Snatch with the parameter that it expects an int, so what am I doing wrong?

like image 981
Vrankela Avatar asked Dec 04 '25 15:12

Vrankela


1 Answers

You need to use one route template to get the desired behavior

//GET weatherforecast/Snatch/1
[Route("[action]/{i:int}")]
[HttpGet]
public IEnumerable<WeatherForecast> Snatch(int i) {
    //...
}

Now as this is an ApiController, it would be enough to use only Http{Verb} for all the actions

When building a REST API, it's rare that you will want to use [Route(...)] on an action method as the action will accept all HTTP methods. It's better to use the more specific Http*Verb*Attributes to be precise about what your API supports. Clients of REST APIs are expected to know what paths and HTTP verbs map to specific logical operations.

//GET weatherforecast/Snatch/1
[HttpGet("[action]/{i:int}")]
public IEnumerable<WeatherForecast> Snatch(int i) {
    //...
}

And this can be simplified even further by aggregating the template

[ApiController]
[Route("[controller]/[action]")] //<-- NOTE THIS
public class WeatherForecastController : ControllerBase {

    //...

    //GET weatherforecast/get
    [HttpGet]
    public IEnumerable<WeatherForecast> Get() {
        //...
    }

    //GET weatherforecast/grab
    [HttpGet]
    public IEnumerable<WeatherForecast> Grab() {
        //...
    }

    //GET weatherforecast/Snatch/1
    [HttpGet("{i:int}")]
    public IEnumerable<WeatherForecast> Snatch(int i) {
        //...
    }
}

Reference Routing to controller actions in ASP.NET Core

Reference Routing in ASP.NET Core

like image 152
Nkosi Avatar answered Dec 07 '25 05:12

Nkosi