2011-03-08 43 views
2

在我的API,我想有一個像GET /api/v1/widgets/1,2,3GET /api/v1/widgets/best-widget,major-widget,bob-the-widget綁定/動作/ 1,2,3列出<int>

public class WidgetsController : MyApiController 
{ 
    public ActionResult Show(IEnumerable<int> ids) 
    { 

    } 

    public ActionResult Show(IEnumerable<string> names) 
    { 

    } 
} 

路線我設置了路線,讓我的動作,但我無法弄清楚如何將1,2,3變成new List<int>(){1, 2, 3}等等。當然,我可以採取一個string並解析它在我的行動,但我想避免走這條路。我想到的一件事是在OnActionExecuting方法中加入了一些東西,但是我不確定在那裏放置什麼東西(顯然我可以一起破解一些東西,但是我正在嘗試寫一些可重用的東西)

我的主要問題是如何知道我是否需要做任何事情(有時ValueProviders上游會計算出所有東西),以及如何處理計算出的類型(例如,如何處理我知道在這種情況下,我需要去一個整數或字符串集合,然後我該怎麼做?)

順便說一下,我有想法實現一個ValueProvider也是如此,但在類似的問題上迷失了方向。

回答

2

我不知道如何將1,2,3轉換爲新的List(){1,2,3}等等。

爲了避免污染需要接收這個參數我會推薦一個自定義的模型綁定每個控制器動作:

public class IdsModelBinder : DefaultModelBinder 
{ 
    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     var result = base.BindModel(controllerContext, bindingContext); 
     var ids = bindingContext.ValueProvider.GetValue("ids"); 
     if (ids != null) 
     { 
      return ids.AttemptedValue 
         .Split(',') 
         .Select(id => int.Parse(id)) 
         .ToList(); 
     } 
     return result; 
    } 
} 

,然後註冊在Application_Start模型綁定:

ModelBinders.Binders.Add(typeof(IEnumerable<int>), new IdsModelBinder()); 

和最後你的控制器動作可能看起來像這樣(從我在你的問題中可以看到它已經看起來像這樣:-)):

public ActionResult Show(IEnumerable<int> ids) 
{ 
    ... 
} 

和自定義模型聯編程序將負責解析ids路由令牌到相應的IEnumerable<int>值。

您可以使用IEnumerable<string>來做相同的操作,您只需刪除相應模型聯編程序中的.Select子句即可。

+0

太好了,謝謝,這就是我一直在尋找的東西。這也應該對我想要做的其他事情有所幫助,例如支持矩陣參數。 – notJim 2011-03-08 14:43:39

+0

剛剛試過這個,它似乎在游泳。我對你的代碼做的一個修改是改變'.GetValue'調用來使用'bindingContext.ModelName'而不是硬編碼名字。我建議編輯你的答案。 – notJim 2011-03-10 01:54:58

0

我是比較新的ASP.Net MVC所以我不知道是否有這樣或沒有更簡單的方法,但是我的做法是這樣做的以下內容:

public class WidgetsController : MyApiController 
{ 
    public ActionResult Show(string ids) 
    { 
     List<int> parsedIds = new List<int>(); 
     foreach (var id in ids.Split(',')) 
     { 
      parsedIds.Add(int.Parse(id)); 
     } 
     return Show(parsedIds); 
    } 

    private ActionResult Show(List<int> ids); 
} 

您可能還想爲輸入的ID無法解析的情況添加一些更復雜的錯誤處理,但那是我將使用的一般方法。

1

如果您的網址是

/api/v1/widgets/Show?names=best-widget&names=major-widget&names=bob-the-widget 

這本身整齊地結合:)

無需重寫modelbinders在這種情況下。 查詢字符串變量names會結合你的節目,method_

public ActionResult Show(IEnumerable<string> names)

希望這有助於!

+0

謝謝,但我試圖避免使用查詢變量。 – notJim 2011-03-08 14:44:30

+0

啊哈!然後你接受了正確的答案:) – 2011-03-08 14:48:45