2012-07-30 39 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逻辑。将尽可能多的逻辑移动到您可以尽可能测试的地方,您会更快乐。