1

私はMVC3に比較的慣れていませんが、MVC3、C#、およびEF4を使用してアプリケーションWebサイトを作成しています。私が使用しているルーティングは、MVC3パターンを選択したときに作成されたデフォルトのMicrosoftプロジェクトと同じですが、特別なことは何もありません。

    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Default", // Route name
            "{controller}/{action}/{id}", // URL with parameters
            new { controller = "Home", action = "Index", id = UrlParameter.Optional }, // Parameter defaults
            new[] { "MySite.Controllers" }
        );
    }

そして、すべてが正常に機能しています。デフォルトのメンバーシッププロバイダーを使用しており、ユーザーはアカウントを識別するINT値も取得します。これにより、次のような単純なルーティングを使用して、プロファイルを非常に簡単に確認できます。

www.mysite.com/profile/4

...例えば。ただし、クライアントは、多くのアカウントを事前に生成して、選択したユーザーに配布するように要求しています。私はSQLServerを介してそれを実行する方法を考案しましたが、それは正常に機能し、すべてのアカウントが作成されました(約1,000)。さらに、これらの事前生成されたアカウントの1つがこれらのユーザーによって「アクティブ化」されているかどうかを識別するのに役立つビットフィールド(「Claimed」)を追加しました。

私の質問は、ユーザーが(アクティブ化されていない)アカウントにアクセスするためのリンクを与えられた場合、そのページで最初のルーティングを行うときにテストを使用して、アカウントが未請求であることを識別し、別の場所に送信して終了する必要があるかどうかです。アカウントに詳細を入力しますか?または、他のすべての人と同じページに移動させ、このレコードを未請求として識別するコントローラーロジックに何かを入れてから、別のページに送信して詳細などの入力を完了する必要がありますか?どちらか一方を実行する正当な理由はありますか?

そして、次のように、Id値を構成する(または誤植がある)人々はどうでしょうか。

www.mysite.com/profile/40000000000

(そしてサイトにはこれまでのところ1000人のユーザーしかいません)、それは同じように扱われるべきですか、それとも完全に異なる手段で扱われるべきですか?(つまり、あるシナリオでは、まだ請求されていない既存のアカウントを特定し、別のシナリオでは、アカウントが存在しないことを把握する必要があります。)

どんな助けでも大歓迎です。

編集:

私はSoliahの提案した解決策を実装しようとしていますが、if(id!= 0)がIDがINTにない可能性があることを気に入らなかったという事実に少し行き詰まりました。私は今それを過ぎて、有効な部分であるかどうかをチェックする方法を見つけようとしていますが、おそらくIDがINTとして扱われないという問題を解決していませんか?データベースの有効性テスト中に再度変換しようとしていますが、間違いなく正しくありません。以下のエラーが発生する理由について何かアイデアはありますか?私は何が欠けていますか?

    public class ValidProfileIdAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var id = (Convert.ToInt32(filterContext.ActionParameters["Id"]));
            if (id != 0)
            {
                // Check if valid and behave accordingly here.
                Profile profile = db.Profiles.Where(q => q.ProfileId == (Convert.ToInt32(id))).FirstOrDefault();
            }
            base.OnActionExecuting(filterContext);
        }
    }


    Cannot implicitly convert type 'System.Linq.IQueryable<Mysite.Models.Profile>' to 'Mysite.Models.Profile'. An explicit conversion exists (are you missing a cast?)

編集#2:

私はロバートの提案に取り組んでおり、部分的に進歩しています。私のコードは現在次のようになっています:

    public class UserAccountActivatedAttribute : ActionMethodSelectorAttribute
    {
        public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            bool isActivated = // some code to get this state 
            return isActivated;
        }
    }

ブログエントリを読んだ後に私が得たもの、そして(信じられないかもしれませんが)この投稿:http://pastebin.com/Ea09Gf4B

物事を再び動かすために、ActionSelectorAttributeをActionMethodSelectorAttributeに変更する必要がありました。

ただし、方法がわからないのは、Id値をboolisActivatedテストに取り込むことです。私のデータベースには、渡されたユーザーのプロファイルIDに応じて、true / false値を返すことができるビュー('Claimed')がありますが、IDを追加する場所がわかりません。ソリアが編集したもののようなものはうまくいくでしょうか?

if (int.TryParse(filterContext.ActionParameters["Id"], id) && id != 0) {

    bool isActivated = db.Claimed.Where(c => c.ProfileId == id).FirstOrDefault();

編集#3:

これが私の現在のコードの状態です:

    public class UserAccountActivatedAttribute : ActionMethodSelectorAttribute
    {
        public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo)
        {
            if (controllerContext == null)
            {
                throw new ArgumentNullException("controllerContext");
            }
            // get profile id first
            int id = int.Parse((string)controllerContext.RouteData.Values["id"]);
            var profile = db.Profiles.Where(q => q.ProfileId == id).FirstOrDefault();
            bool isActivated = profile;// some code to get this state 
            return isActivated;
        }
    }

私にとっては、それらを機能させるためにint.Parse((string)controllerContext.RouteData.Valuesに変更する必要がありました。これは(その時点で)機能しているようです。)ここでフォーマットすることを発見しました:routevalueをプロパティにバインドするビューモデルの一部であるオブジェクトの

この線

var profile = db.Profiles.Where(q => q.ProfileId == id).FirstOrDefault();

dbのエラー。セクション、次のようなエラーメッセージが表示されます。

ネストされたタイプ「MySite.Controllers.HomeController.UserAccountActivatedAttribute」を介して外部タイプ「MySite.Controllers.HomeController」の非静的メンバーにアクセスできません

...これは私がMSDNとStackで熱心に理解しようとしたものですが、空になってしまいました。これはベルを鳴らしますか?

4

4 に答える 4

3

他の人はすでに多くのことを提案していますが、ここで何か他のものをテーブルに持ってきましょう。

アクションメソッドセレクター

コントローラのアクションをクリーンに保つために、アクションメソッドセレクタ属性を記述して、2つの単純なアクションを作成できます。

[ActionName("Index")]
public ActionResult IndexNonActivated(int id)
{
    ...
}

[ActionName("Index")]
[UserAccountActivated]
public ActionResult IndexActivated(int id)
{
    ...
}

このように、アクションのコードをチェックして、アクションを本当に薄く保つ必要はありません。セレクターフィルターは、ユーザーアカウントのアクティブ化状態に関連して正しいアクションが実行されることを確認します。

アクションセレクターの属性について詳しくは、私のブログ投稿をご覧ください。ただし、基本的には、次のようなものを作成する必要があります。

public class UserAccountActivatedAttribute : ActionMethodSelectorAttribute
{
    public override bool IsValidForRequest(ControllerContext controllerContext, MethodInfo methodInfo)
    {
        if (controllerContext == null)
        {
            throw new ArgumentNullException("controllerContext");
        }

        // get profile id first
        int id = int.Parse(controllerContext.RouteData.Values["id"] ?? -1);

        bool isActivated = // some code to get this state 

        return isActivated;
    }
}

そしてそれは基本的にそれです。

これにより、アカウントがアクティブ化されているかどうかに関係なく、ユーザーは自分のプロファイルにアクセスできるようになります。または、後で非アクティブ化することもできます...そしてバックグラウンドでシームレスに動作します。

1つの重要な利点

(Jurajが提案するように)異なる名前の2つのアクションがあり、1つはアクティブなプロファイル用で、もう1つはアクティブ化用である場合、アクティブなユーザーでもアクティブ化アクションにアクセスできるため、両方をチェックインする必要があります。

profile/4 > for active profiles
profile/activate/4 > for inactive profiles

両方のアクションは、状態をチェックし、その状態が「適合」しない場合に相互にリダイレクトする必要があります。これは、リダイレクトが発生するたびに、プロファイルが2回チェックされることも意味します。各アクションで。

アクションメソッドセレクターは、プロファイルを1回だけチェックします。ユーザープロファイルの状態に関係なく。

于 2012-05-16T07:21:10.120 に答える
0

アカウントがアクティブ化されているかどうかを確認することは、アプリケーション ロジックの一部であり、コントローラー内 (またはより深い部分) に実装する必要があります。コントローラー内で、アクティブ化されていないユーザーを他のコントローラー/アクションにリダイレクトして、アクティブ化を完了することができます。URL ルーティング メカニズムは、着信 URL の形状に従って単純にルーティングする必要があり、データベースに接続する必要はありません。

于 2012-05-15T10:30:15.420 に答える
0

彼/彼女がアクティブ化されると、同じリンクを使用してプロファイルにアクセスできるようになる可能性があるため、コントローラーにそのロジックを含めることをお勧めします。

于 2012-05-15T04:18:06.633 に答える