How to pass multiple parameters to a get method in ASP.NET Core

411,789

Solution 1

You also can use this:

// GET api/user/firstname/lastname/address
[HttpGet("{firstName}/{lastName}/{address}")]
public string GetQuery(string id, string firstName, string lastName, string address)
{
    return $"{firstName}:{lastName}:{address}";
}

Note: Please refer to the answers from metalheart and Mark Hughes for a possibly better approach.

Solution 2

Why not using just one controller action?

public string Get(int? id, string firstName, string lastName, string address)
{
   if (id.HasValue)
      GetById(id);
   else if (string.IsNullOrEmpty(address))
      GetByName(firstName, lastName);
   else
      GetByNameAddress(firstName, lastName, address);
}

Another option is to use attribute routing, but then you'd need to have a different URL format:

//api/person/byId?id=1
[HttpGet("byId")] 
public string Get(int id)
{
}

//api/person/byName?firstName=a&lastName=b
[HttpGet("byName")]
public string Get(string firstName, string lastName, string address)
{
}

Solution 3

To parse the search parameters from the URL, you need to annotate the controller method parameters with [FromQuery], for example:

[Route("api/person")]
public class PersonController : Controller
{
    [HttpGet]
    public string GetById([FromQuery]int id)
    {

    }

    [HttpGet]
    public string GetByName([FromQuery]string firstName, [FromQuery]string lastName)
    {

    }

    [HttpGet]
    public string GetByNameAndAddress([FromQuery]string firstName, [FromQuery]string lastName, [FromQuery]string address)
    {

    }
}

Solution 4

I would suggest to use a separate dto object as an argument:

[Route("api/[controller]")]
public class PersonController : Controller
{
    public string Get([FromQuery] GetPersonQueryObject request)
    {
        // Your code goes here
    }
}

public class GetPersonQueryObject 
{
    public int? Id { get; set; }
    public string Firstname { get; set; }
    public string Lastname { get; set; }
    public string Address { get; set; }
}

Dotnet will map the fields to your object.

This will make it a lot easier to pass through your parameters and will result in much clearer code.

Solution 5

I think the easiest way is to simply use AttributeRouting.

[Route("api/YOURCONTROLLER/{paramOne}/{paramTwo}")]
    public string Get(int paramOne, int paramTwo)
    {
        return "The [Route] with multiple params worked";
    }
Share:
411,789

Related videos on Youtube

mstrand
Author by

mstrand

Updated on November 12, 2021

Comments

  • mstrand
    mstrand over 2 years

    How can I pass in multiple parameters to Get methods in an MVC 6 controller. For example I want to be able to have something like the following.

    [Route("api/[controller]")]
    public class PersonController : Controller
    {
        public string Get(int id)
        {
        }
    
        public string Get(string firstName, string lastName)
        {
    
        }
    
        public string Get(string firstName, string lastName, string address)
        {
    
        }
    }
    

    So I can query like.

    api/person?id=1
    api/person?firstName=john&lastName=doe
    api/person?firstName=john&lastName=doe&address=streetA
    
  • metalheart
    metalheart about 8 years
    why would you need this? parameter binding from the query string happens by default...
  • mstrand
    mstrand about 8 years
    I have tried both but overloading as I try to do fails with or without [FromQuery]
  • mstrand
    mstrand about 8 years
    Yes, I solve it now using just one action taking in all attributes that I want to be able to search out a Person on. Like a general search. I would prefer though if there where a way to have overloaded actions in a controller but that might not be the case.
  • Mark Hughes
    Mark Hughes about 8 years
    @mstrand I've updated - give that a go, see the extra [HttpGet] annotations, the different method names, and the specific route in [Route] - the routes should be fully explicit now which eliminates a few possible problems.
  • Seb Andraos
    Seb Andraos over 6 years
    As stipulated in the documentation for parameter binding[1] simple types, "(int, bool, double, and so forth), plus TimeSpan, DateTime, Guid, decimal, and string" will automatically be read fro the URI. The attribute [FromURI] is required when the parameter in not one of these types to force the reading of those from the URI rather than their default location, the body. For the sake of completeness the [FromBody] attribute does essentially the opposite with complex types. [1] docs.microsoft.com/en-us/aspnet/web-api/overview/…)
  • Phillip Copley
    Phillip Copley over 6 years
    Until you need to get everyone with the same last name :)
  • ZZZ
    ZZZ about 6 years
    this does not work with .net core 2.0, since no valid url template is actually generated.
  • k4s
    k4s about 5 years
    Can I use preferred reference type? That is, int paramOne, string paramTwo
  • Thomas Levesque
    Thomas Levesque almost 5 years
    That's a really bad way to design API routes... Not RESTful at all.
  • Anytoe
    Anytoe almost 5 years
    Use [Route("api/YOURCONTROLLER/{paramOne}/{paramTwo?}")] if you want your second parameter to be optional
  • Bernoulli IT
    Bernoulli IT almost 5 years
    The above approach looks very cumbersome, don't get why it has so many upvotes.
  • Bruno Santos
    Bruno Santos over 4 years
    @ThomasLevesque What did you mean by it no being RESTful?
  • Thomas Levesque
    Thomas Levesque over 4 years
    @BrunoSantos it doesn't follow the principles of REST. URIs are supposed to uniquely identify resources. This is not the case here (there might be multiple persons with the same first and last name, and an address can certainly not be considered an identifier)
  • Bruno Santos
    Bruno Santos over 4 years
    @ThomasLevesque Oh I see what you mean, my question though is: having 3 params to uniquelly identify a resource, instead of just 1 param, is it a bad practice?
  • Thomas Levesque
    Thomas Levesque over 4 years
    @BrunoSantos no, not that in itself. My issue is only about the route design in this specific case.
  • Arie
    Arie over 3 years
    and how to pass values in link?
  • Sebastian
    Sebastian over 3 years
    What do mean with that? You can provide the values as query parameters like /api/controller?firstname={firstname}&lastname={lastname}
  • Sabir Hossain
    Sabir Hossain over 3 years
    @metalheart without [FromQuery] sometimes the first param value comes as the RouteName
  • Ashok Patel
    Ashok Patel over 3 years
    If you have single parameter to pass this is good approach, otherwise should use query string
  • Naveen Kumar V
    Naveen Kumar V over 3 years
    Good and Simple one :)
  • Oleg Ivanov
    Oleg Ivanov almost 3 years
    I can't believe such answers receive so many upvotes. Do you really build your api in such way?
  • Chris Fremgen
    Chris Fremgen over 2 years
    @OlegIvanov Care to share your answer? Or contribute anything useful?
  • RedRose
    RedRose about 2 years
    This is good when you have a growing and long list of filters and sort criteria and you want to keep the your endpoint simple and offload the validation and parsing of query to another class or service.
  • ZecosMAX
    ZecosMAX about 2 years
    Your solution should have a checked sing. It's simple and does exactly what was requested.
  • Onurkan Bakırcı
    Onurkan Bakırcı about 2 years
    This is not suitable for API conventions. By the question firstname, lastname and address should be passed as query params not route params.