2012-12-31 30 views
3

現在我想的圖案有「當前用戶」在我的行動modelbinded參數。currentUser作爲modelbinded參數

我的行爲會是這個樣子:

public JsonResult ListStuff(User currentUser, string paramter1, int parameter2) 
{ 
} 

而且我有一個非常簡單的模型綁定器,看起來像這樣:

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
{ 
    if (bindingContext.ModelName == "currentUser") 
     return Globals.HttpContextItems.User; 

    return null; 
} 

我真的很喜歡該操作是不太依賴於另一個控制器屬性。它更清楚地說明了這些函數的「輸入參數」是什麼,它更具可重用性,並且將來會使它更易於測試。

我有點affraid的安全問題雖然。我可能必須非常確定(即在DefaultModelBinder中)currentUser將永遠不會被其他ModelBinder自動綁定。

誰能照亮一盞燈,如果這可能是一個很好的模式,如果有東西,我目前還不想着,但是,這將使在未來的問題。

+0

我會說它是模型綁定的反模式。 Modelbinding不依賴於參數的名稱。它依賴於類型。屬性的答案可能更接近,我會允許該屬性在它的ctor中接受一個字符串,所以它並不總是「currentUser」 –

+0

有趣的是這個。但是你怎麼看待這個'約定配置'方式呢?是不是這樣的,你必須命名你的Controller SomeNameController。或者你的意見是在一個名爲Views的文件夾中並自動找到的? –

+0

約定優於配置沒有問題。問題是在這種情況下,約定與類型匹配。通過參數名稱進行匹配違反了現有的約定。 –

回答

2

如果您擔心其他ModelBinders將設置參數,爲什麼不創建一個ActionFilterAttribute,讓你顯式地去裝飾你的操作方法:

public class GetCurrentUserAttribute : ActionFilterAttribute 
{ 
    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     filterContext.ActionParameters["currentUser"] = filterContext.HttpContext.User; 
    } 
} 

然後使用它:

[GetCurrentUser] 
public ActionResult Index(User currentUser) 
{ 
} 

絕對不像默認的模型綁定器那麼幹淨,但更加明確。

+0

你可以使它成爲一個globacl過濾器。 – SLaks

+1

確實如此,但我喜歡能夠輕鬆確定值的設置位置的想法。 –

+0

這很聰明。我已經在不同級別的授權中使用自定義的AuthorizationAttributes。所以我可能會將它們更改爲ActionFilterAttributes,並且可以直接在其中設置參數。 –

1

有趣的想法。我喜歡通過在方法中注入需求來保持與IoC的一致性(人們常常忘記可以將依賴關係注入方法,而不僅僅是構造函數)。

你的安全問題會被抽象的,你會填充此背景下的項目的位置。我的建議是將相同的邏輯放在上下文項目中,放在同一個位置。在兩個地方有一個這樣的邏輯(一個模型綁定器,然後說一個控制器方法),你需要追蹤兩個地方來追蹤一個錯誤。我說這個模型聯編程序應該負責加載該上下文項目,如果它是空的。

最後,這將抽象甚至遠更爲複雜的「用戶驗證」中如果你想做到這一點的未來服務。例如,我一次有一個項目需求,以確保通過安全檢查將每個數據和ID傳遞到屬於該用戶的域中。你所描述的這種方法向你提供的是有一個自定義的用戶對象,它繼承自你的用戶對象,叫做UserContext : User,它可以有許多其他UI相關的功能和屬性 - 包括附加的安全性布爾驗證。

我可以在我的下一個項目的嘗試。