2008-11-17 47 views
4

這可能太想了一個問題,但尋求幫助!ASP.NET MVC - 用戶輸入和服務/存儲庫 - 在哪裏做驗證?

我一直在努力改進我的ASP.NET MVC程序結構。我剛開始在預覽版5上使用它,這是我第一次進入商業應用程序開發 - 所以每一個都是新的!

在控制器級別,我有責任與版本庫,並採取所有的業務邏輯的護理服務對象。在動作級別,我有一個保存所有視圖數據的對象 - 用戶輸入和生成的輸出 - 我將調用視圖對象(這是否有一個通用術語?)。與我看到的大多數示例不同,此對象不是數據庫對象,而是特定於視圖的對象。

所以現在我要添加用戶驗證。問題是,我不知道該把它放在哪裏。對我來說,最重要的是在服務層中完成它。服務層負責所有業務邏輯,驗證是業務邏輯。另一方面,我所看到的大多數驗證框架都用於驗證對象,這讓我認爲視圖對象應該是驗證意識。最後,還有一些需要數據庫連接的驗證方法(例如檢查用戶輸入字段是否具有相應的數據庫記錄),並且視圖對象沒有數據庫的概念,只有服務。

所以一些選項我看到的是:

  • 驗證是否在傳遞到方法的參數Service.Method。
  • 在調用Service.Method之前在視圖對象中進行驗證。
  • 在視圖對象中進行驗證,但是使Service.Method需要一個視圖對象引用,以便它啓動對該對象的驗證。

我敢肯定有更多。我很好奇其他人如何處理MVC意義上的用戶輸入驗證。我以前使用過企業驗證塊,並且喜歡能夠使用股票驗證器來處理所有事情,但我不確定如何使它適合單獨的視圖對象和服務層。如果他們(視圖對象/服務)是同一個對象,這也許是人們做的事情,那將是容易的事情?就像我說的,它對我來說都是新的,我正在尋找最佳實踐/模式。

回答

6

我通常做的時候提交表單的控制器動作基本驗證(必填字段,電子郵件格式等)。然後,我讓業務層處理需要業務知識的驗證。我通常會仔細檢查業務層中的基本內容,因此如果我通過Web服務公開該邏輯或稍後在其他應用程序中使用該邏輯,那麼我仍然會驗證其最重要的地方(IMO)。

1

看看S#arp Architecture項目。驗證在模型上進行處理,以確保沒有實體以無效狀態持久保存到數據庫。它通過使用NHibernate.Validator並將其附加到NHibernate的保存和更新事件來完成。

就個人而言,這種做法是很有道理的我,因爲你沒有複製在多個控制器的驗證邏輯。

4

有這個

就我個人而言,我已向我的服務層對象(前兩個鏈接)添加了驗證。這樣,如果任何方法在任何控制器決定調用我的服務方法..邏輯都在一個位置檢查和裝箱。 DRY

這就是說,我也有一些UI驗證(第三鏈接)..以減少往返時間。

最後,當前的MVC DLL有能力將錯誤消息傳遞迴UI ..所以視圖可以很好地顯示它們。退房: -

  • ViewData.ModelState.AddModelError(密鑰,消息)

心連心!

1

我怕我的帖子沒有回覆,很高興錯了!

我已經閱讀過這些鏈接,但可能在一個月或更久之前,重新閱讀我現在瞭解的內容對我非常有幫助。我真的很喜歡史蒂夫桑德森的職位,但希望他能展示一個證明右邊的東西的例子。

作爲他博客中的一個示例,他給出了:「'用戶名必須是唯一的'可能會在您的數據庫中強制執行」。因此,這會不會是這樣的:

public static void SavePerson(Person person) 
{ 
    // make sure it meets some format requirement 
    // in this case the object is responsible for validation and the service layer is the caller 
    person.EnsureValid(); 

    // todo: action to verify username is unique by checking database 
    // in this case the service layer is responsible for calling and implementing validation 

    // todo: action to save to database 
} 

這是有道理的,並且能顯示出我的麻煩抓往哪裏放審定它既是服務層(非常獨特的名字)和視圖對象(驗證格式)內。

我的另一個問題是服務層開始帶驗證邏輯。也許把它分成不同的班級或別的什麼?在我的情況下,一些驗證邏輯可能會在服務之間共享,所以我想想一個乾的方法來實現這一點。有趣的東西想想!

Emad Ibrahim的鏈接很棒,因爲一旦我開始理解這個過程,我將尋找一種方法來使用相同的一組規則生成javascript客戶端驗證,而無需重複代碼。他已經有了:)

我聽說過S#arp,但沒有坐下來,看到它是如何工作的(我不確定是否有很多演示的方式,或者如果下載代碼是演示!)。我不確定是否僅對數據庫模型進行驗證就足夠了。在我看來,對於業務邏輯所說的無效數據庫(比如日期範圍/必須在/之前/之後),會有很多有效的模型狀態。這些都是那些令人頭大我的大腦:)

同樣的情況下,鏈接我喜歡(GOOGLE了它後,我看到了伊馬德答覆史蒂夫發佈與BLL和不知道是什麼意思......杜):

http://en.wikipedia.org/wiki/Business_logic_layer

所以我不知道它,但我認爲這是我正在寫的模型:處理數據交互的Business Process對象,以及邏輯模型而非數據庫模型的業務實體。我想我需要開始閱讀一些更基本的模式和實踐,以更好地理解這些概念(看起來很多這是Java人寫的東西與.NET人的東西)。它可能是時候退一步:)

0

我在最近的項目中遇到過這個相同的問題。首先,爲了重申問題,我試圖遵循以域爲中心的DDD方法。我將實體組合成可以驗證自己的聚合體,並且存儲庫在保存時驗證有效性。 UI還可以從聚合中獲取有效性信息,以向客戶顯示錯誤反饋。一般的方法是儘可能地利用ASP.NET MVC的模型綁定和驗證/表單UI幫助器。這創建了簡單的UI流程:1)綁定,2)驗證,3)如果有效,保存,否則重新填充視圖。

但是,如何在涉及DDD服務的情況下如何充分利用ASP.NET MVC和這種簡單的流程並不直接。本來,我發展我的服務,例如:

public class SomeProcessService 
{ 
    public Result Execute(int anAggregateID, int anotherAggregateID, string someData) 
    { 
    // validate input 

    // if invalid, return failures 

    // else 
    // modify aggregates 
    // using (transaction) 
    // { 
    //  save aggregates 
    //  commit 
    // } 

    // return success 
    } 
} 

的問題是,驗證和保存的方法是密不可分的。爲了利用MVC模型綁定,我們需要一些可以作爲綁定模型的東西。我重構此:

public class SomeProcessService 
{ 
    public class Request : IValidateable 
    { 
    public int AggregateID {get;set;} 
    public int AnotherAggregateID {get;set;} 
    public string SomeData {get;set;} 

    public Result Validate() 
    { 
     // validation 
    } 
    } 

    public void Execute(Request request) 
    { 
    // validate input by calling request.Validate() 

    // if invalid, throw new ValidationException(request) 

    // else 
    // modify aggregates 
    // using (transaction) 
    // { 
    //  save aggregates 
    //  commit 
    // } 

    // return success 
    } 
} 

這repurposes的Parameter Object pattern到單獨的方法輸入驗證。我可以綁定到我的控制器中的SomeProcessService.Request對象,並在那裏獲取驗證信息。如果一切正常,則從我的控制器使用Request對象作爲參數發起服務調用。這種方法似乎很高興將DDD服務與ASP.NET MVC驗證要求結合在一起。