ASP.NET Core의 get 메서드에 여러 매개 변수를 전달하는 방법


107

MVC 6 컨트롤러의 Get 메서드에 여러 매개 변수를 어떻게 전달할 수 있습니까? 예를 들어 다음과 같은 것을 가질 수 있기를 원합니다.

[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)
    {

    }
}

그래서 나는 같은 쿼리를 할 수 있습니다.

api/person?id=1
api/person?firstName=john&lastName=doe
api/person?firstName=john&lastName=doe&address=streetA

답변:


91

다음을 사용할 수도 있습니다.

// 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}";
}

참고 : metalheart의과를 참조하십시오 metalheartMark Hughes가능성이 더 나은 접근 방식.


21
당신은 : 같은 성을 가진 사람 얻을 필요까지
필립 코플리

14
이것은 API 경로를 설계하는 정말 나쁜 방법입니다. 전혀 RESTful이 아닙니다.
Thomas Levesque

7
위의 접근 방식은 매우 번거롭게 보이지만 왜 그렇게 많은 찬성 투표가 있는지 이해하지 마십시오.
Bernoulli IT

1
@ThomasLevesque RESTful이 아니라는 의미는 무엇입니까?
Bruno Santos 19 년

2
@BrunoSantos는 REST의 원칙을 따르지 않습니다. URI는 리소스를 고유하게 식별해야합니다. 이 여기에 (이 같은 성과 이름을 가진 여러 사람이 될 수도 있고, 주소는 확실히 식별자로 간주 될 수 없다) 사실이 아니다
토마스 레베

60

하나의 컨트롤러 동작 만 사용하지 않는 이유는 무엇입니까?

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);
}

또 다른 옵션은 속성 라우팅을 사용하는 것이지만 다른 URL 형식이 필요합니다.

//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)
{
}

예, 저는 Person을 검색 할 수 있기를 원하는 모든 속성을 취하는 단 하나의 작업으로 해결합니다. 일반적인 검색과 같습니다. 컨트롤러에서 오버로드 된 작업을 수행하는 방법이있는 경우 선호하지만 그렇지 않을 수도 있습니다.
mstrand

3
유효한 URL 템플릿이 실제로 생성되지 않았기 때문에 .net core 2.0에서는 작동하지 않습니다.
ZZZ

44

URL에서 검색 매개 변수를 구문 분석하려면 컨트롤러 메소드 매개 변수에로 주석을 추가해야합니다 [FromQuery]. 예를 들면 다음 과 같습니다.

[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)
    {

    }
}

6
왜 이것이 필요합니까? 쿼리 문자열 바인딩 매개 변수는 ... 기본적으로 발생
metalheart

1
나는 둘 다 시도했지만 [FromQuery]를 사용하거나 사용하지 않고 실패하려고 할 때 과부하가 발생했습니다
mstrand

2
@mstrand 업데이트했습니다. 추가 [HttpGet]주석, 다른 메서드 이름 및 특정 경로를 확인 [Route]하십시오. 이제 경로가 완전히 명시되어 몇 가지 가능한 문제가 제거되어야합니다.
마크 휴즈

9

가장 쉬운 방법은 AttributeRouting.

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

선호하는 참조 유형을 사용할 수 있습니까? 즉,int paramOne, string paramTwo
k4s

두 번째 매개 변수를 선택 사항으로 지정하려면 [Route ( "api / YOURCONTROLLER / {paramOne} / {paramTwo?}")]를 사용하세요
Anytoe

8

별도의 dto 개체를 인수로 사용하는 것이 좋습니다.

[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은 필드를 개체에 매핑합니다.

이렇게하면 매개 변수를 훨씬 더 쉽게 전달할 수 있고 훨씬 더 명확한 코드가 생성됩니다.


5

웹 API 코어에서 여러 매개 변수로 get을 호출하려면

  [ApiController]
    [Route("[controller]")]
    public class testController : Controller
    {

      [HttpGet]
        [Route("testaction/{id:int}/{startdate}/{enddate}")]
        public IEnumerable<classname> test_action(int id, string startdate, string enddate)
        {

            return List_classobject;
        }

    }

In web browser
https://localhost:44338/test/testaction/3/2010-09-30/2012-05-01

3

다른 답변 후 귀하의 의견에서 요청한 오버로딩에 대한 자세한 내용을 추가하려면 여기에 요약이 있습니다. 주석은 ApiControllerGET쿼리에서 어떤 작업이 호출되는지 보여줍니다 .

public class ValuesController : ApiController
{
    // EXPLANATION: See the view for the buttons which call these WebApi actions. For WebApi controllers, 
    //          there can only be one action for a given HTTP verb (GET, POST, etc) which has the same method signature, (even if the param names differ) so
    //          you can't have Get(string height) and Get(string width), but you can have Get(int height) and Get(string width).
    //          It isn't a particularly good idea to do that, but it is true. The key names in the query string must match the
    //          parameter names in the action, and the match is NOT case sensitive. This demo app allows you to test each of these
    //          rules, as follows:
    // 
    // When you send an HTTP GET request with no parameters (/api/values) then the Get() action will be called.
    // When you send an HTTP GET request with a height parameter (/api/values?height=5) then the Get(int height) action will be called.
    // When you send an HTTP GET request with a width parameter (/api/values?width=8) then the Get(string width) action will be called.
    // When you send an HTTP GET request with height and width parameters (/api/values?height=3&width=7) then the 
    //          Get(string height, string width) action will be called.
    // When you send an HTTP GET request with a depth parameter (/api/values?depth=2) then the Get() action will be called
    //          and the depth parameter will be obtained from Request.GetQueryNameValuePairs().
    // When you send an HTTP GET request with height and depth parameters (/api/values?height=4&depth=5) then the Get(int height) 
    //          action will be called, and the depth parameter would need to be obtained from Request.GetQueryNameValuePairs().
    // When you send an HTTP GET request with width and depth parameters (/api/values?width=3&depth=5) then the Get(string width) 
    //          action will be called, and the depth parameter would need to be obtained from Request.GetQueryNameValuePairs().
    // When you send an HTTP GET request with height, width and depth parameters (/api/values?height=7&width=2&depth=9) then the 
    //          Get(string height, string width) action will be called, and the depth parameter would need to be obtained from 
    //          Request.GetQueryNameValuePairs().
    // When you send an HTTP GET request with a width parameter, but with the first letter of the parameter capitalized (/api/values?Width=8) 
    //          then the Get(string width) action will be called because the case does NOT matter.
    // NOTE: If you were to uncomment the Get(string height) action below, then you would get an error about there already being  
    //          a member named Get with the same parameter types. The same goes for Get(int id).
    //
    // ANOTHER NOTE: Using the nullable operator (e.g. string? paramName) you can make optional parameters. It would work better to
    //          demonstrate this in another ApiController, since using nullable params and having a lot of signatures is a recipe
    //          for confusion.

    // GET api/values
    public IEnumerable<string> Get()
    {
        return Request.GetQueryNameValuePairs().Select(pair => "Get() => " + pair.Key + ": " + pair.Value);
        //return new string[] { "value1", "value2" };
    }

    //// GET api/values/5
    //public IEnumerable<string> Get(int id)
    //{
    //    return new string[] { "Get(height) => height: " + id };
    //}

    // GET api/values?height=5
    public IEnumerable<string> Get(int height) // int id)
    {
        return new string[] { "Get(height) => height: " + height };
    }

    // GET api/values?height=3
    public IEnumerable<string> Get(string height)
    {
        return new string[] { "Get(height) => height: " + height };
    }

    //// GET api/values?width=3
    //public IEnumerable<string> Get(string width)
    //{
    //    return new string[] { "Get(width) => width: " + width };
    //}

    // GET api/values?height=4&width=3
    public IEnumerable<string> Get(string height, string width)
    {
        return new string[] { "Get(height, width) => height: " + height + ", width: " + width };
    }
}

궁금한 경우를 대비하여 단일 경로 만 필요합니다.

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );

이 MVC보기 또는 유사한 것으로 모든 것을 테스트 할 수 있습니다. 예, JavaScript와 마크 업을 혼합해서는 안되며 평소처럼 부트 스트랩을 사용하지 않는다는 것을 알고 있지만 이것은 데모 목적으로 만 사용됩니다.

<div class="jumbotron">
    <h1>Multiple parameters test</h1>
    <p class="lead">Click a link below, which will send an HTTP GET request with parameters to a WebAPI controller.</p>
</div>
<script language="javascript">
    function passNothing() {
        $.get("/api/values", function (data) { alert(data); });
    }

    function passHeight(height) {
        $.get("/api/values?height=" + height, function (data) { alert(data); });
    }

    function passWidth(width) {
        $.get("/api/values?width=" + width, function (data) { alert(data); });
    }

    function passHeightAndWidth(height, width) {
        $.get("/api/values?height=" + height + "&width=" + width, function (data) { alert(data); });
    }

    function passDepth(depth) {
        $.get("/api/values?depth=" + depth, function (data) { alert(data); });
    }

    function passHeightAndDepth(height, depth) {
        $.get("/api/values?height=" + height + "&depth=" + depth, function (data) { alert(data); });
    }

    function passWidthAndDepth(width, depth) {
        $.get("/api/values?width=" + width + "&depth=" + depth, function (data) { alert(data); });
    }

    function passHeightWidthAndDepth(height, width, depth) {
        $.get("/api/values?height=" + height + "&width=" + width + "&depth=" + depth, function (data) { alert(data); });
    }

    function passWidthWithPascalCase(width) {
        $.get("/api/values?Width=" + width, function (data) { alert(data); });
    }
</script>
<div class="row">
    <button class="btn" onclick="passNothing();">Pass Nothing</button>
    <button class="btn" onclick="passHeight(5);">Pass Height of 5</button>
    <button class="btn" onclick="passWidth(8);">Pass Width of 8</button>
    <button class="btn" onclick="passHeightAndWidth(3, 7);">Pass Height of 3 and Width of 7</button>
    <button class="btn" onclick="passDepth(2);">Pass Depth of 2</button>
    <button class="btn" onclick="passHeightAndDepth(4, 5);">Pass Height of 4 and Depth of 5</button>
    <button class="btn" onclick="passWidthAndDepth(3, 5);">Pass Width of 3 and Depth of 5</button>
    <button class="btn" onclick="passHeightWidthAndDepth(7, 2, 9);">Pass Height of 7, Width of 2 and Depth of 9</button>
    <button class="btn" onclick="passHeightWidthAndDepth(7, 2, 9);">Pass Height of 7, Width of 2 and Depth of 9</button>
    <button class="btn" onclick="passWidthWithPascalCase(8);">Pass Width of 8, but with Pascal case</button>
</div>

1

여기에 이미지 설명 입력

NB-I remove FromURI. 여전히 URL에서 값을 전달하고 결과를 얻을 수 있습니다. fromuri를 사용하여 benfifts를 아는 사람이 있으면 알려주십시오.


매개 변수 바인딩 [1] 단순 유형에 대한 문서에 규정 된대로 "(int, bool, double 등) 및 TimeSpan, DateTime, Guid, decimal 및 string"이 URI에서 자동으로 읽 힙니다. [FromURI] 속성은 이러한 유형 중 하나가 아닌 매개 변수가 기본 위치 인 본문이 아닌 URI에서 읽기를 강제 할 때 필요합니다. 완전성을 위해 [FromBody] 속성은 기본적으로 복잡한 유형과 반대의 역할을합니다. [1] docs.microsoft.com/en-us/aspnet/web-api/overview/… )
Seb

1

다음을 수행 할 수 있습니다.

    [HttpGet]
    public async Task<IActionResult> GetAsync()
    {
        string queryString = Request.QueryString.ToString().ToLower();

        return Ok(await DoMagic.GetAuthorizationTokenAsync(new Uri($"https://someurl.com/token-endpoint{queryString}")));
    }

각 요소에 개별적으로 액세스해야하는 경우을 참조하십시오 Request.Query.


1

방법은 다음과 같아야합니다.

[Route("api/[controller]")]
public class PersonsController : Controller
{
    [HttpGet("{id}")]
    public Person Get(int id)

    [HttpGet]
    public Person[] Get([FromQuery] string firstName, [FromQuery] string lastName, [FromQuery] string address)
}

두 번째 메소드는 객체 배열을 반환하고 컨트롤러 이름은 plurar (Persons not Person)에 있습니다.

따라서 ID로 리소스를 얻으려면 다음과 같습니다.

api/persons/1

이름 등의 검색 기준으로 개체를 가져 오려면 다음과 같이 검색 할 수 있습니다.

api/persons?firstName=Name&...

그리고 그 사람의 명령을 받고 싶다면 (예를 들어) 다음과 같이 진행해야합니다.

api/persons/1/orders?skip=0&take=20

그리고 동일한 컨트롤러의 방법 :

    [HttpGet("{personId}/orders")]
    public Orders[] Get(int personId, int skip, int take, etc..)

0
    public HttpResponseMessage Get(int id,string numb)
    {

        using (MarketEntities entities = new MarketEntities())
        {
          var ent=  entities.Api_For_Test.FirstOrDefault(e => e.ID == id && e.IDNO.ToString()== numb);
            if (ent != null)
            {
                return Request.CreateResponse(HttpStatusCode.OK, ent);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Applicant with ID " + id.ToString() + " not found in the system");
            }
        }
    }

0

가장 간단한 방법,

제어 장치:

[HttpGet("empId={empId}&startDate={startDate}&endDate={endDate}")]
 public IEnumerable<Validate> Get(int empId, string startDate, string endDate){}

우편 배달원 요청 :

{router}/empId=1&startDate=2020-20-20&endDate=2020-20-20

학습 포인트 : 정확한 패턴 요청은 컨트롤러에 의해 수락됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.