3

私はあらゆる種類の .NET Web 開発に非常に慣れていません (これまでのところ、主に Winforms とサービスを扱ってきました)。他の 2 人の開発者と既存の MVC3 プロジェクトに取り組み始めました。私は概念的に MVC に精通しており、このプロジェクトで MVC がどのように使用されているかを把握しようとしています。

アカウントを表す AccountDto クラスがあります。各エンティティの別のクラス、つまり AccountResponse に継承される Response クラスがあります。

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; }
}

AccountDto オブジェクトのリストとともに、AccountResponse を Controller に返す AccountService があります。

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;
}

成功/失敗メッセージを処理できるように 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 メソッドは、これらの Response オブジェクトから DTO を解析する必要もあります。これは私にはアンチパターンのように思えます。このようなアプローチは正常ですか?

これが長すぎる場合はお詫びします。Code Review または別のサイトに属している場合は移行してください。

4

2 に答える 2

4

これがアンチパターンになることに同意します。ビューは、特にこのようなロジックについては、まったく無知であると想定されています。

成功と失敗の違いがUIの小さな部分である場合、これが魅力的である理由はわかりますが、それが変わるとしたら想像してみてください. ビューには、完全に異なるビューに切り替える機能がほとんどありません (パーシャルの不要なネストなし)。リダイレクトやその他のエラー コードを発行する機能はありません。UI を変更することにした場合は、コントローラーに戻ってもう一度書き直す必要がある場合があります。

ロジックをビューに移動する理由がresponse.IsSuccessController からロジックを削除することだった場合 (正直なところ、それは問題ないように思えます。クラシックとほとんど同じModel.IsValidです)、別のアプローチを検討できます:Responseクラスを次のようにリファクタリングします。から継承しActionResultます。次に、そのロジックをExecuteResult()メソッドに移動すると、コントローラーから分離されます。

于 2012-07-30T17:44:38.040 に答える
1

合体演算子を使用するだけで、多くのクラフト (奇妙な Response 基本クラス (存在し続ける場合は抽象としてマークする必要があります) など) を取り除き、null チェックを回避できます。

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

さらに良いことに、そのロジックをサービス クラスに移行して、オブジェクトが確実に返されるようにします (バッキング エンティティがない場合にリポジトリがこれを行うのは必ずしも意味がありませんが、サービスの場合は意味があります)。

いずれにせよ、見苦しい null チェックや if/else ロジックをビューに含める必要はありません。できるだけ多くのロジックをテストできる場所に移動してください。

于 2012-07-30T17:51:44.157 に答える