我对任何类型的.NET Web开发都很陌生(到目前为止,我主要使用Winforms和服务。)我已经开始与另外两个开发人员合作开发一个现有的MVC3项目。我在概念上熟悉MVC,并试图了解它在这个项目中是如何使用的。
我们有一个AccountDto类来表示帐户。有一个Response类,由每个实体的另一个类继承,即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; }
}
有一个AccountService会将一个AccountResponse返回给Controller,其中包含一个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切换到使用Response,因此必须在视图中处理成功/失败:
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方法然后还必须从这些Response对象解析DTO。这对我来说似乎是一种反模式;是这样的方法吗?
如果这太冗长,请致歉,如果它属于Code Review或其他网站,请迁移。
答案 0 :(得分:4)
我同意你的意见,这将是一种反模式。视图应该是非常无知的,特别是像这样的逻辑。
如果成功与失败之间的差异只是UI的一小部分,我可以理解为什么这会很诱人,但想象一下如果要改变。视图几乎没有能力(没有不必要的局部嵌套)来切换到完全不同的视图。它具有 no 发出重定向或其他错误代码的能力。如果您决定更改UI,则可能需要再次返回并重新调整Controller。
如果将逻辑移到视图背后的原因是从Controller中删除response.IsSuccess
逻辑(说实话,这对我来说似乎很好;它与经典{{1}几乎相同}),您可以考虑另一种方法:重构您的Model.IsValid
类以继承Response
。然后,您可以将该逻辑移动到ActionResult
方法中,它将与您的Controller分开。
答案 1 :(得分:1)
只需使用coalesce运算符,就可以摆脱一大堆错误(就像那个奇怪的Response基类(如果它继续存在则应该标记为抽象))并避免空值检查。
public ActionResult ToBeCalled(int id)
{
var response = _accountService.GetAccountByAccountId(id) ??
new AccountResponse();
return View(response);
}
更好的是,将该逻辑迁移到您的服务类中,以便它保证返回一个对象(当没有后台实体时,存储库执行此操作并不一定有意义,但它对服务有效。) / p>
无论哪种方式,您都不需要在视图中包含难看的空检查或if / else逻辑。将尽可能多的逻辑移动到你可以测试它的地方,你会更快乐。