배열을 ASP.NET MVC 컨트롤러 동작 매개 변수로 받아들이는 방법은 무엇입니까?


85

Designs다음 서명이있는 작업 이있는 ASP.net MVC 컨트롤러 가 있습니다.

public ActionResult Multiple(int[] ids)

그러나 URL을 사용하여이 작업으로 이동하려고 할 때 :

http://localhost:54119/Designs/Multiple?ids=24041,24117

ids매개 변수는 항상 null입니다. MVC에서 ?ids=URL 쿼리 매개 변수를 작업에 대한 배열로 변환하는 방법이 있습니까? 액션 필터를 사용하는 것에 대한 이야기를 보았지만 URL 자체가 아닌 요청 데이터에서 배열이 전달되는 POST에서만 작동합니다.

답변:


150

기본 모델 바인더는 다음 URL을 예상합니다.

http://localhost:54119/Designs/Multiple?ids=24041&ids=24117

성공적으로 바인딩하려면 :

public ActionResult Multiple(int[] ids)
{
    ...
}

그리고 이것이 쉼표로 구분 된 값으로 작동하도록하려면 사용자 정의 모델 바인더를 작성할 수 있습니다.

public class IntArrayModelBinder : DefaultModelBinder
{
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
    {
        var value = bindingContext.ValueProvider.GetValue(bindingContext.ModelName);
        if (value == null || string.IsNullOrEmpty(value.AttemptedValue))
        {
            return null;
        }

        return value
            .AttemptedValue
            .Split(',')
            .Select(int.Parse)
            .ToArray();
    }
}

그런 다음이 모델 바인더를 특정 작업 인수에 적용 할 수 있습니다.

public ActionResult Multiple([ModelBinder(typeof(IntArrayModelBinder))] int[] ids)
{
    ...
}

또는 모든 정수 배열 매개 변수에 전 세계적으로 적용 Application_StartGlobal.asax:

ModelBinders.Binders.Add(typeof(int[]), new IntArrayModelBinder());

이제 컨트롤러 작업은 다음과 같습니다.

public ActionResult Multiple(int[] ids)
{
    ...
}

2
나는 실종되었다 [FromUri]. public ActionResult Multiple([FromUri]int[] ids) {} (GET)
C0d1ngJammer

1
@Darin이 사용자 지정 바인딩을 전역 적으로 적용하지만 특정 작업을 무시하는 방법이 있습니까? 방법을 찾을 수 없습니다. stackoverflow.com/questions/45379040/…
akd

15

Darin Dimitrov의 답변 을 확장하려면 stringURL 매개 변수에서 간단한 것을 받아들이고 직접 배열로 변환하는 것이 좋습니다 .

public ActionResult Multiple(string ids){
  int[] idsArray = ids.Split(',').Select(int.Parse).ToArray();
  /* ...process results... */
}

이 작업을 수행하는 동안 구문 분석 오류가 발생하면 (누군가가 잘못된 배열을 전달했기 때문에), 예외 처리기가 엔드 포인트를 찾을 수 없을 때 MVC가 반환하는 400 Bad Request더 비 친화적 인 기본 오류 대신 오류 를 반환하도록 할 수 있습니다 404 Not Found.


9

이 URL 형식을 사용할 수도 있으며 ASP.NET MVC가 모든 작업을 수행합니다. 그러나 URL 인코딩을 적용하는 것을 잊지 마십시오.

?param1[0]=3344&param1[1]=2222

6

Groky의 URL 문자열이 어디에서 왔는지 모르겠지만 컨트롤러 / 액션을 호출하는 일부 자바 스크립트에서 동일한 문제가 발생했습니다. null다중 선택 목록 (공유 할 솔루션에 고유함)에서, 1 또는 여러 "ID" 의 URL을 구축합니다 .

Darin의 커스텀 모델 바인더를 복사 / 붙여 넣기하고 액션 / 파라미터를 장식했지만 작동하지 않았습니다. 나는 여전히 null가치를 얻었다 int[] ids. 실제로 ID가 많은 "안전한"경우에도 마찬가지입니다.

결국 다음과 같은 ASP.NET MVC 친화적 인 매개 변수 배열을 생성하도록 자바 스크립트를 변경했습니다.

?ids=1&ids=2

어리석은 짓을해야했는데

ids || []                 #=> if null, get an empty array
[ids || []]               #=> if a single item, wrap it in an array
[].concat.apply([], ...)  #=> in case I wrapped an array, flatten it

그래서 전체 블록은

ids = [].concat.apply([], [ids || []])
id_parameter = 'ids=' + ids.join('&ids=')

지저분하지만 자바 스크립트에서 이와 같이 해킹 한 것은 처음입니다.


1
마지막 문장에서 "처음"앞에 누락 된 'not'이 있는지 궁금합니다. 그렇지 않으면 행운아!
DCShannon

1
@DCShannon : 하하, 나는 당신의 요점을 봅니다! 하지만 이번이 처음이었습니다. 이런 일이 정상인지 아니면 배 밖으로 나가는 지 잘 모르겠습니다.
Anthony Mastrean

0

.Net 핵심 답변

최근에 여기에 오는 사람들을 위해 .Net Core에서 다음과 같이 할 수 있습니다.

http://localhost:54119/Designs/Multiple?ids=24041&ids=24117

과:

public ActionResult Multiple([FromQuery] int[] ids)
{
    ...
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.