ASP.NET 웹 API의 선택적 쿼리 문자열 매개 변수


212

다음 WebAPI 메소드를 구현해야합니다.

/api/books?author=XXX&title=XXX&isbn=XXX&somethingelse=XXX&date=XXX

모든 쿼리 문자열 매개 변수는 null 일 수 있습니다. 즉, 호출자는 0에서 5 개의 매개 변수를 모두 지정할 수 있습니다.

MVC4 베타 에서는 다음을 수행했습니다.

public class BooksController : ApiController
{
    // GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
    public string GetFindBooks(string author, string title, string isbn, string somethingelse, DateTime? date) 
    {
        // ...
    }
}

MVC4 RC는 더 이상이 동작을하지 않습니다. 5 개 미만의 매개 변수를 지정하면 다음과 같이 응답합니다 404.

컨트롤러 '도서'에서 요청과 일치하는 조치가 없습니다.

URL 라우팅에서 선택적 매개 변수를 지정하지 않고 이전과 같이 동작하도록하는 올바른 메소드 서명은 무엇입니까?


[httpget]을 실행하십시오.
user960567

2
모든 매개 변수를 설정하면 메서드가 호출됩니다. 또한 그것은 방법 Get으로 자동으로 바인딩됩니다 HTTP GET...
frapontillo

이 웹 API를 작품, 라우팅 방법이다 asp.net/web-api/overview/web-api-routing-and-actions/...
user960567을

4
예. 나는 그것이 어떻게 작동하는지 안다. 나는이 특정 상황에서 작동하도록 할 수 없습니다.
frapontillo

이것은 어떻게 컴파일 되었습니까? string?유효한 유형이 아닙니다. string참조 유형이므로 널 입력 가능 유형으로 선언 할 수 없습니다 .
EkoostikMartin

답변:


307

이 문제는 MVC4 정식 릴리스에서 수정되었습니다. 이제 할 수있는 일 :

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}

모든 것이 즉시 작동합니다.


여기서 null을 기본값으로 사용할 수 있습니까? 예를 들어 : string author = null?
보리스 진 첸코

2
예, 상수 표현식null 으로 간주 되므로 유효한 기본값입니다 .
JDawg

여기서 말한 것처럼 선택적 매개 변수에 대해서도 왜 기본값을 언급해야하는지 궁금 합니다 . C #의 모든 유형은 항상 기본값을 가지므로 라우팅 런타임이 URI에서 유형을받지 못하면 유형의 기본값을 사용할 수 있습니다. 이것의 기술적 이유는 무엇입니까? 나는 이것이 모델 바인더와 관련이 있다고 확신합니다.
RBT

@RBT 경로를 일치시킬 수 있도록
James Westgate

날짜 매개 변수를 사용하고 있었고 null 매개 변수로 설정하면 작동하지 않습니다. 따라서 nullable과 null을 기본값으로 설정하고 그에 따라 서버 측 유효성 검사를 사용하고 오류 메시지를 다시 반환해야합니다. 효과가있었습니다.
Atta H. 19

85

vijay가 제안한대로 여러 매개 변수를 단일 모델로 전달할 수 있습니다. FromUri 매개 변수 속성을 사용할 때 GET에 적용됩니다. 이것은 WebAPI에게 쿼리 매개 변수에서 모델을 채우도록 지시합니다.

그 결과 단 하나의 매개 변수만으로보다 깔끔한 컨트롤러 작업이 가능합니다. 자세한 내용은 다음을 참조 하십시오 : http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api

public class BooksController : ApiController
  {
    // GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
    public string GetFindBooks([FromUri]BookQuery query)
    {
      // ...
    }
  }

  public class BookQuery
  {
    public string Author { get; set; }
    public string Title { get; set; }
    public string ISBN { get; set; }
    public string SomethingElse { get; set; }
    public DateTime? Date { get; set; }
  }

속성이 충돌하지 않는 한 여러 매개 변수도 지원합니다.

// GET /api/books?author=tolk&title=lord&isbn=91&somethingelse=ABC&date=1970-01-01
public string GetFindBooks([FromUri]BookQuery query, [FromUri]Paging paging)
{
  // ...
}

public class Paging
{
  public string Sort { get; set; }
  public int Skip { get; set; }
  public int Take { get; set; }
}

업데이트 :
값을 선택적으로 사용하려면 모델 속성에 참조 유형 또는 nullable (예 : int?)을 사용해야합니다.


4
예. 그러나 [FromUri] 데코레이터만으로는 선택적 매개 변수를 지원하지 않습니다.
John Meyer

6
@JohnMeyer [FromUri]를 올바르게 사용하면 원래 질문에 직접 대답하지 않습니다. 기본적으로 이러한 모델을 Uri의 값으로 채 웁니다. 선택 사항을 지원하려면 모델 특성이 널 입력 가능 또는 참조 유형이어야합니다. 추가 정보가 추가되었습니다.
Andrew C

@AndrewC-값이 선택적인지 확인하기 위해 nullable을 사용해야하는시기와 이유에 대해 자세히 설명해 주시겠습니까? 값을 nullable로 설정하지 않고 (예 : property int Skip) 지정된 속성에 대한 쿼리 매개 변수가 지정되지 않은 경우 API Controller 메소드는 여전히 요청과 일치 Skip하며 해당 값은 해당 유형의 기본값입니다. 이 경우 0
클락

2
@Clark-널 입력 가능 유형을 사용하지 않으면 사용자가 값을 제공하지 않았고 초기화되지 않은 유형 값 (int의 경우 0)을 얻었는지 또는 사용자가 0을 지정했는지 알 수 없습니다. 널 입력 가능을 사용하면 사용자가이를 정의하지 않은 채로 둘 수 있습니다 따라서 컨트롤러 작업에서 기본값을 안전하게 적용 할 수 있습니다. 위의 예에서 Take를 보면 Take에 대해 0을 받으면 어떻게해야합니까? 사용자가 0 개의 레코드를 요청했거나 지정하지 않았으므로 모든 레코드를 가져와야합니다. 일반적으로 값 유형 (int, bool 등)을 선택적으로 사용하려면 널 입력 가능해야합니다.
Andrew C

70

아래와 같은 모든 매개 변수에 초기 기본값 사용

public string GetFindBooks(string author="", string title="", string isbn="", string  somethingelse="", DateTime? date= null) 
{
    // ...
}

1
이것은 올바른 절차이지만 한 가지 경우 DateTime는 nullable이 아닙니다. 이미 DateTime?대신 사용하려고했지만 HTTP 요청에 매개 변수 중 일부만 설정하면 MVC가 요청을 지정된 메소드에 매핑하지 않습니다.
frapontillo

DateTime.Parse () 함수를 사용하여 날짜를 문자열로 전달하고 컨트롤러 함수 내에서 구문 분석 할 수 있습니다.
Muhammad Amin

1
@MuhammadAmin DateTime널 입력 가능 데이터 유형 이 아닙니다 . nulltype 유형의 매개 변수에 값을 지정할 수 없으므로 코드가 컴파일되지 않아야 합니다 DateTime. 아마도로 변경하거나과 DateTime?같은 기본값으로 다른 값을 사용해야 DateTime.Now합니다.
Ivaylo Slavov

1
@IvayloSlavov DateTime.Now는 컴파일 시간 상수가 아니므로 기본 매개 변수로 할당 할 수 없습니다.
GiriB

@GiriB, 당신 말이 맞아요. Datetime.Now기본 매개 변수 초기화에 사용할 수 없습니다.
Ivaylo Slavov 2018 년

1

여러 매개 변수를 전달하려는 경우 여러 매개 변수를 전달하는 대신 모델을 만들 수 있습니다.

매개 변수를 전달하지 않으려는 경우 건너 뛸 수 있으며 코드가 깔끔하고 깔끔하게 보입니다.


1
이는 요청 본문의 POST 매개 변수에만 해당됩니다. URL의 매개 변수는 여전히 개별적으로 인수로 참조 할 수 있습니다.
Nathan

1

' optional'로 선언되지 않은 매개 변수에는 기본값을 제공 할 수 없습니다

 Function GetFindBooks(id As Integer, ByVal pid As Integer, Optional sort As String = "DESC", Optional limit As Integer = 99)

당신의 WebApiConfig

 config.Routes.MapHttpRoute( _
          name:="books", _
          routeTemplate:="api/{controller}/{action}/{id}/{pid}/{sort}/{limit}", _
          defaults:=New With {.id = RouteParameter.Optional, .pid = RouteParameter.Optional, .sort = UrlParameter.Optional, .limit = UrlParameter.Optional} _
      )

8
실제로 그들은 할 수 있습니다. VB.NET이 아닌 C #을 사용하고 있습니다.
frapontillo
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.