2015-05-06 49 views
2

我有一個現有的API我正轉向WebAPI,所以我不能自由更改URL。打破現有的客戶不是我的選擇。按值類型區分的WebAPI控制器方法

瞭解到,原始API會接受給定操作方法的Guid(ID)或字符串(名稱)。舊的API處理程序將破譯URL參數並將請求發送到旨在接受給定參數類型的控制器操作。

作爲一個例子:

Get(Guid id) 

Get(string name) 

隨着的WebAPI,參數綁定是跨值類型貪心,所以根據其第一控制器源文件中,該操作是被調用的那個。爲了我的需要,這不起作用。我希望binder會認識到轉換爲Guid會失敗,然後選擇更通用的基於字符串的操作。沒有骰子。 Guid只是一個空值(有趣的是,因爲它是一個值類型,但這正是我在調試器中處理中的某個點時所獲得的值)。

所以我的問題是如何最好地處理這個問題?我需要去實現一個自定義的IHttpActionSelector嗎?我嘗試過使用屬性路由方法(有約束),但是這種方法工作不正確(因爲它看起來很酷)。 WebAPI中是否有一種機制可以解釋我不知道的情況? (我知道我可以通過測試Guid-ness字符串並調用其他控制器方法來破解它,但我希望有更優雅的基於WebAPI的解決方案......)

+0

'Guid'出現'null'?聽起來很腥。 'string'不是一個值類型。你如何發佈這些數據? –

+0

它實際上是在寫入處理流水線中的ETags的屬性中變爲null。該屬性查看命名參數的路由動作參數,但沒有找到它。 (你是對的,Guid實際上不能爲空......我只是沒有給你所有的細節。) – Kenn

回答

0

我花了一個很多時候嘗試適應基於屬性的路由,但我沒有那個工作。但是,我確實使用路由約束來解決我的特定問題。如果首先註冊更受限制的路由,WebAPI(如MVC)將應用約束並跳過限制更多的路由,直到找到可供選擇的路由(如果有)。

因此,使用我的榜樣,我會設置路線,像這樣:

_config.Routes.MapHttpRoute(name: "ById", 
    routeTemplate: "product/{id}", 
    defaults: new { controller = "ProductDetails" }, 
    constraints: new { id = @"^\{?[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{4}-[0-9A-Fa-f]{12}\}?$" }); 
_config.Routes.MapHttpRoute(name: "ByName", 
    routeTemplate: "product/{name}", 
    defaults: new { controller = "ProductDetails" }); 

第一條路線接受了一個GUID正則表達式的形式約束。第二個接受所有其他值,控制器將處理非產品名稱(返回404)。我在自己託管的WebAPI服務器中測試了它,並且它非常有效。

我相信基於屬性的路由會更優雅,但直到我得到它的工作,它是我的舊路。至少我發現了一個合理的基於WebAPI的解決方案。