3

私の MVC4 アプリでは、ログインしているかどうか (私の場合は FormsAuthentication) に応じて異なる動作をする必要があるアクションがいくつかあります。

たとえば、「RenderAccountAndProfile」メソッドを持つ AccountController があります。ログアウトすると、対応する部分ビューにログイン プロンプトとボタンが表示されます。ユーザーがログインしている場合、ユーザーのプロファイル リンクがログアウト ボタンの横に表示されます。

私がこれまでプロジェクトで採用してきたアプローチは、単純に if ステートメントを線に沿って配置することです...

        if (HttpContext.User.Identity.IsAuthenticated)
        {
            ...
        }
        else
        {
            ...
        }

ただし、このアプローチのかなりエレガントな代替手段と思われるものを作成しました。

非常に単純な AnonymousUsersOnly という新しい属性を作成しました。

public class AnonymousUsersOnlyAttribute : System.Web.Mvc.ActionMethodSelectorAttribute
{
    public override bool IsValidForRequest(System.Web.Mvc.ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
    {
        return !controllerContext.HttpContext.User.Identity.IsAuthenticated;
    }
}

私の AccountController クラスは Authorize 属性で装飾されています。これにより、次のコードを使用できるようになりました。

[Authorize]
public class AccountController : Controller
{
    [AllowAnonymous]
    [AnonymousUsersOnly]
    [ActionName("RenderAccountAndProfile")]
    public ActionResult RenderAccountAndProfile_Anonymous()
    {
        // create a "logged out" view model
        return Content("**NOT LOGGED IN** - LOG IN HERE");
    }

    [ActionName("RenderAccountAndProfile")]
    public ActionResult RenderAccountAndProfile_Authorized()
    {
        // create a "logged in" view model
        return Content("**LOGGED IN** - LOG OUT");
    }
}

私のアクション メソッドは単一責任の原則に準拠しているため、このアプローチは非常に気に入っています。各メソッドは、ログイン状況またはログアウト状況のいずれかのみを処理するようになりました。トラフィックを誘導する「if」ステートメントはもう必要ありません。

これにより、各メソッドが 2 つではなく 1 つの結果のみに関係するようになったため、単体テストも容易になるはずです。単体テストを記述して、各結果を個別にテストし、異なるメソッドを呼び出すことができます。

明らかに、同じ署名を持つ 2 つのメソッドを持つことはできないため、ActionName 属性を使用する必要があります。

ここであなたの批評をいただければ幸いです。これはエレガントなソリューションだと思いますか? このアプローチの長所と短所は何ですか? また、これにはどのようなセキュリティへの影響/リスクがありますか?

4

2 に答える 2

3

ここでの問題は、戦略パターンの問題です。そして、非常に巧妙な実装で、(非標準の) 戦略パターンを実装しました。賢すぎるのではないかと心配です。その巧妙さにより、初心者にはコードが何をしているのかがあまりわかりません。

率直に言って、私は気にしない方がいいと思います。私はよく、ドメイン オブジェクト/サービスに対する非常に薄いアダプターとしてコントローラーを記述します。したがって、コントローラーの設計を完璧にするために、実用的なアプローチを採用したいと考えています。わずかな設計上の問題と明白なコードとの間で決定を下す際には、常に明白なコードを選択してください。

より厚いコントローラーを使用している場合、またはここでこの問題を本当に懸念するその他の理由がある場合は、認証状態に基づいて異なる戦略の実装を提供する抽象ファクトリによっておそらく支援される、より伝統的な戦略パターンを検討することができます。これは設計の目的を満たし、他のプログラマー (設計パターンを知っている場合) にすぐになじみます。

そうは言っても、あなたの巧妙な解決策を維持することはそれほど害になるとは思いません. 名前を変更したくなるでしょう。拒否は、私には奇妙な動詞のように思えます。おそらくAnonymousUsersOnly、それは将来のプログラマーにとってもう少しコミュニケーションがとれるでしょう。

于 2012-12-09T04:33:39.587 に答える