9

私はデスクトップ ソフトウェア開発の経験があり、ASP.NET MVC の学習を始めています。

デフォルトの HomeController には、次のようなコードを持つ Index アクションがあります。

if (!Request.IsAuthenticated)
    return RedirectToAction("Login", "Account");

つまり、ユーザーを「/account/login」にリダイレクトします。AccountController.Login アクションはユーザーを処理し、ユーザーが正常にログインすると、ユーザーを HomeController に送り返します。

このコードは、私がデスクトップ ソフトウェアで別の方法で行うことに慣れているためか、匂いがします。Login アクションの名前を「LogOn」に変更するとどうなりますか? AccountController を完全に削除して別のものに置き換えるとどうなりますか? 新しいバグを導入しますが、コンパイラ エラーは発生しません。また、単体テストでもそれをキャッチできない可能性があります。コントローラーとアクションの名前を指定するために文字列を使用したため、リファクタリングと再設計により、コード全体が壊れる可能性が高くなります。

私が欲しいのは次のようなものです:

if (!Request.IsAuthenticated)
    return RedirectToAction(() => AccountController.Login);

ただし、それが可能かどうか、またはそれが最善の方法であるかどうかはわかりません。

私は愚かですか、それとも他の人も同じ問題を抱えていますか? それを回避するために何をしますか?

4

7 に答える 7

20

あなたが探しているのは、T4MVCが存在する理由だと思います。T4MVCは、コントローラーとアクションに関連するすべての「魔法の文字列」を削除し、それらをクラスとプロパティに置き換えます。

T4MVCでは、これ

if (!Request.IsAuthenticated)
    return RedirectToAction("Login", "Account");

これになります

if (!Request.IsAuthenticated)
    return RedirectToAction(MVC.Account.Login());

T4MVC設定で設定できるフラグがあり、ビルドごとにテンプレートを強制的に実行し、何かが変更された可能性がある場合に早期に警​​告します。

AuthorizeAttribute要求した内容ではありませんが、を使用して、要求がコントローラーアクション内で認証されているかどうかを確認する必要をなくすことを検討できます。

これ

public class HomeController : Controller
{
    public ActionResult Index() 
    {
        if (!Request.IsAuthenticated)
            return RedirectToAction("Login", "Account"); 

        // .... carry on
    }
}

になります

public class HomeController : Controller
{
    [Authorize]
    public ActionResult Index() 
    {
        // .... carry on
    }
}

次に、web.configで、アカウントのログインURLを指すようにURLを設定します

<authentication mode="Forms">
   <forms loginUrl="account/login" timeout="30" />
</authentication> 

確かに、これはコントローラーとアクションが変更された場合(元の苦情と同様)に安全性を提供しませんが、選択したURLを適切なコントローラーとアクションに転送し、T4MVCで生成されたクラスを使用するルートをいつでも設定できます。ルート。状況が変わった場合にコンパイル時の警告を提供します。

于 2011-12-03T21:20:19.637 に答える
5

C# 6 ではnameof、これらの魔法の文字列の多くを利用して簡単にリファクタリングできます。

... = new SelectList(context.Set<User>(), nameof(User.UserId), nameof(User.UserName));

...
return RedirectToAction(nameof(Index));
于 2016-02-01T22:10:33.530 に答える
4

You can write your own custom extension methods to help you avoid magic strings. For example you can see my implementation here: https://github.com/ivaylokenov/ASP.NET-MVC-Lambda-Expression-Helpers Keep in mind this adds a little bit of performance overhead run-time which you can solve by caching all the links. If you want compile time checking T4MVC is your solution: http://t4mvc.codeplex.com/

于 2015-06-03T07:29:50.750 に答える
3

私はそれが本当に答えではないことを知っていますが、Resharperのようなツールを使用することもこれを解決するのに役立ちます。Resharperは、コントローラーとアクションを追跡し、コントローラーであるはずのマジックストリングが1つでない場合は、警告を発行します。ただし、RedirectToActionやActionLinkなどの標準メソッドでのみ機能します。

編集:どうやら、カスタム拡張メソッドで機能するようにアノテーションを追加できます。ここを参照してください。

于 2011-12-03T21:37:11.060 に答える
1

Russの答えは正しいですが、実際にはあなたの懸念に対処していません..これは、「MVCに魔法の文字列があるのはなぜですか?」です。

MVC の初期のバージョンでは、実際にはかなり異なっていました。彼らは魔法の文字列を使用せず、より型ベースのメソッドを持っていました。ただし、これはいくつかの理由で変更されました。詳細は忘れてしまいましたが、型保証されていないメソッドへの逆戻りには論理的な理由がありました。

MVC が一致する規則を求めて複数の領域を検索する方法に関係していた可能性があることを思い出したようです。これは、型付きオブジェクトよりも文字列で実現する方がはるかに簡単でした。これは特にビューとパーシャルに当てはまります。

詳細を覚えている誰かが声をかけてくれるかもしれません。

于 2011-12-04T07:19:20.990 に答える
0

アクションとコントローラーへのリダイレクトだけが本当に気になる場合は、C# 6nameofオペレーターが非常に役立ちます (コントローラー間のリダイレクトが必要になるまでは)。コントローラー名を取得するためのユーティリティメソッドを作成しました。

public class Utilities
{
    public static string ControllerName<T>() where T : Controller
    {
        var name = typeof(T).Name;
        return name.Substring(0, Math.Max(name.LastIndexOf(nameof(Controller), 
                                          StringComparison.CurrentCultureIgnoreCase), 0));
    }
}

そして、次のように使用できます。

public ActionResult Foo()
{
    return RedirectToAction(nameof(HomeController.Index), 
                            Utilities.ControllerName<HomeController>());
}
于 2016-09-19T00:42:50.443 に答える