2012-07-30 64 views
3

我對任何一種.NET Web開發都很陌生(迄今爲止我主要在Winforms和服務上工作)。我已經開始與其他兩個開發人員一起開發現有的MVC3項目。我在概念上熟悉MVC,並試圖追趕它在這個項目中的使用方式。這是一個MVC反模式嗎?

我們有一個AccountDto類來表示帳戶。這裏是由另一個類繼承的每個實體的響應類,即AccountResponse:

public class Response 
{ 
    [DataMember] 
    public bool IsSuccess{get;set;} 

    [DataMember] 
    public string DisplayMessage { get; set; } 

    [DataMember] 
    public string DetailedMessage { get; set; } 

    [DataMember] 
    public ErrorType ErrorType { get; set; } 

    public Response(){ 
     this.IsSuccess=true; 
     this.ErrorType = ErrorType.None; 
    } 
} 

public partial class AccountResponse : Response 
{ 
    [DataMember] 
    public IList<AccountDto> AccountList { get; set; } 
} 

有將一個AccountResponse返回到控制器上的帳戶服務,與AccountDto對象的列表:

public AccountResponse GetAccountByAccountId(Int64 accountId) 
{ 
    _logger.Info("Executing GetAccountByAccountId()"); 
    AccountResponse response = new AccountResponse(); 

    try 
    { 
     Account item = AccountPersistence.GetAccountByAccountId(accountId); 
     AccountDto dto = Mapper.Map<AccountDto>(item); 

     response.AccountList = new List<AccountDto>() { dto }; 
     response.IsSuccess = true; 
    } 
    catch (Exception ex) 
    { 
     response.IsSuccess = false; 
     response.ErrorType = ErrorType.GeneralFault; 
     response.DetailedMessage = ex.ExceptionMessageBuilder(); 
     response.DisplayMessage = "System Failure: Failed to get Account by AccountId"; 
     _logger.Error(ex); 
    } 
    return response; 
} 

我被告知響應事件被實現爲能夠處理成功/失敗消息。因此,在一個控制器,還有像下面的(未發生做任何特殊,如果失敗)代碼:

public ActionResult ToBeCalled(int id) 
{ 
    AccountDto dto = null; 
    var response = _accountService.GetAccountByAccountId(Convert.ToInt64(id)); 
    if (response.IsSuccess) 
    { 
     dto = response.AccountList[0]; 
     return View(dto); 
    } 
    return View(dto); 
} 

這是有道理的,我雖然我不知道在哪裏成功/錯誤消息,打算被利用。然而,他們現在想要從視圖中使用響應使用DTO切換,所以成功/失敗將在意見進行處理:

public ActionResult ToBeCalled(int id) 
{ 
    var response = _accountService.GetAccountByAccountId(Convert.ToInt64(id)); 
    return View(response); 
} 

這似乎離我 - 而不是編碼針對DTO作爲模型,我必須做類似的每一頁下面:

@{ 
    if (Model.IsSuccess) 
    { 
     var account = Model.AccountList.FirstOrDefault(); 

     if (account != null) 
     { 
      @Html.HiddenFor(x => account.AccountNumber) 
     } 
} 

的控制器的ActionResult/HttpPost方法,那麼也必須從這些響應對象分析DTO。這對我來說似乎是一種反模式;這種方法是否正常?

道歉,如果這太長,請遷移,如果它屬於代碼審查或其他網站。

+1

我工作的第一個MVC項目,幾乎完全相同的模式(實際上略微可怕)已經到位,我的想法和你完全一樣。 FWIW我同意下面的@bhamlin – glosrob 2012-07-30 17:48:07

回答

4

我同意你,這將是一個反模式。該視圖應該是相當無知的,尤其是像這樣的邏輯。

如果成功與失敗之間的差異只是UI的一小部分,我可以理解爲什麼這是誘人的,但想象一下如果這種變化。視圖幾乎沒有能力(沒有不必要的部分嵌套)切換到完全不同的視圖。它有沒有發出重定向或其他錯誤代碼的能力。如果您決定更換用戶界面,則可能需要返回並重新編寫Controller。

如果將邏輯移動到視圖背後的原因是從控制器中刪除response.IsSuccess邏輯(說實話,這看起來對我來說很好,它與典型的Model.IsValid幾乎相同),您可以考慮另一個方法:重構您的Response類以繼承ActionResult。然後,您可以將該邏輯移至ExecuteResult()方法中,並且它將與控制器分開。

1

只需使用coalesce操作符,就可以擺脫一大堆cruft(就像那個奇怪的Response基類(應該被標記爲抽象的,如果它繼續存在的話))並避免空值檢查。

public ActionResult ToBeCalled(int id) 
{ 
    var response = _accountService.GetAccountByAccountId(id) ?? 
     new AccountResponse(); 
    return View(response); 
} 

更重要的是,這種邏輯遷移到服務類,以便它可以保證一個對象(這並不一定意義對儲存要做到這一點時,有沒有靠山實體的回報,但它確實爲服務)。

無論哪種方式,您不需要在視圖中包含難看的空檢查或if/else邏輯。將盡可能多的邏輯移動到您可以儘可能測試的地方,您會更快樂。