2012-02-29 61 views
58

我有一個名爲設計的ASP.net MVC控制器,具有以下簽名的動作:如何接受數組作爲ASP.NET MVC控制器操作參數?

public ActionResult Multiple(int[] ids) 

然而,當我嘗試使用網址導航到這一行動:

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

的ids參數始終爲空。有沒有什麼辦法讓MVC將?id = URL查詢參數轉換爲動作數組?我已經看到了使用動作過濾器的說法,但據我所知,這隻適用於數組在請求數據而不是URL本身中傳遞的POST。

回答

110

默認的model binder希望這個網址:

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

爲了成功地結合到:

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

如果你想這與逗號分隔值工作,你可以寫一個自定義模式binder:

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

然後您可以將此模型綁定器應用於某個特定AR行動的說法:

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

或全局應用到所有整數數組參數在Application_StartGlobal.asax

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

,現在你的控制器動作可能是這樣的:

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

我錯過了'[FromUri]'。 'public ActionResult Multiple([FromUri] int [] ids){} **(GET)** – C0d1ngJammer 2017-05-22 13:22:09

+0

@Darin是否有一種方法可以在全局範圍內應用自定義綁定,但只是忽略特定操作?我找不到這樣做的方法:https://stackoverflow.com/questions/45379040/how-to-override-global-model-binder-for-speacific-post-action-mvc5 – akd 2017-07-28 23:59:26

8

你也可以使用這種URL格式,ASP.NET MVC將爲你做所有事情。但是,請記住應用網址編碼。

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

我不知道在哪裏Groky的URL字符串是從哪裏來的,但我有一些javascript調用我的控制器/動作有同樣的問題。它將構建一個URL爲null,1或多個選擇列表中的許多「ID」(這對我將要共享的解決方案來說是唯一的)。

我複製/粘貼達林的自定義模型聯編程序並修飾了我的動作/參數,但沒有奏效。我仍然有null價值int[] ids。即使在我確實有很多ID的「安全」情況下。

我最終改變的JavaScript產生一個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=') 

這很麻煩,但這是我第一次在JavaScript中使用這種方式進行破解。

+1

只是好奇,如果有一個在最後一句「第一次」之前缺少「不」。否則,幸運的你! – DCShannon 2015-03-24 00:40:09

+1

@DCShannon:哈哈,我明白你的意思了!但是,這是我第一次。我不確定這種事情是否正常,或者我是否過度。 – 2015-03-25 13:31:42

7

要延長Darin Dimitrov's answer,有些東西你可以在你的URL參數接受一個簡單的string並將其轉換爲一個數組自己脫身:

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

如果你得到,而這樣做解析錯誤(因爲某人向您傳遞了一個格式錯誤的數組),您可能會導致您的異常處理程序返回一個400 Bad Request錯誤,而不是默認的,更不友好的404 Not Found錯誤,即在未找到端點時MVC返回。

相關問題