2011-06-25 10 views
14

Asp.net MVCアプリケーションのアカウント登録には、一般ユーザー用のアカウント登録と、特定の登録トークンに登録しているユーザー用の2つの方法があります。したがって、私は私のAccountControllerに次のメソッドのシグネチャを持っている:私はhttp://localhost/Account/Registerに行くときAsp.net MVCは、異なるパラメータを持つ2つのアクションを区別できないのはなぜですか?

public virtual ActionResult Register() {...} 

public virtual ActionResult Register (Guid registrationToken) {...} 

はしかし、私は、現在の要求は、これら2つのアクション間曖昧であるという例外を取得します。私は、registrationToken GETパラメータが渡されなかった場合、パラメータなしのRegisterアクションを使用するという印象を受けました。それ以外の場合は、2番目を使用します。

これには特別なルート設定が必要ですか?

答えて

14

null可能なパラメータを持つ1つのメソッドを持つ方が簡単でしょうか?これにより、もはやあなたの問題は自動的に解消されます。

public virtual ActionResult Register (Guid? registrationToken) 
{ 
    if(registrationToken.HasValue) 
    { 
     // this is specific user 
    }   
    else 
    { 
     // this is general user 
    } 
} 
+0

ええ、それは1つの解決策ですが、私はMVCによって自動化されたソリューションを期待していました。私は、MVCがパラメータによってアクション間を区別できると思っただけです。 – KallDrexx

+2

@KallDrexx - 問題は、 'no parameter'と 'parameter is null'を区別しないことです。同様に 'パラメータ 'a'がセットされ、パラメータ' b'がヌルで、パラメータ名 'a'がセットされ、パラメータ' b'はありません。単純なケースでは明白に思えるかもしれませんが、これは難解なケースでは実装が容易ではありません。これは非常に複雑でバグの多い意思決定の枠組みとなるでしょう。 –

+0

それは意味がある – KallDrexx

3

2番目の方法で投稿が必要ですか?フォーム提出を受け入れるために使用されるメソッドの上に[HttpPost]を追加すると、通常は有益です。

また、問題を解決することもあります。

+0

いいえ、どちらのメソッドも登録フォームを提示することを目的としていますユーザに提供する。後者はより特殊な形式のものであり、前者は一般的な形式のものです。その場合は – KallDrexx

+0

という名前をつけているのですが、なぜあなたはそれらに同じ名前をつけようとしているのか分かりません。 –

11

mvcコントローラのデフォルトベースクラスControllerは、呼び出すアクションを選択するのにActionInvokerを使用します。最初に、アクションはが選択され、デフォルトではRouteData ["action"]値からが選択され、選択されたアクションのパラメータに対するすべてのモデルのバインドと検証が行われます。そのため、呼び出し元が同じ名前で同じ属性を持つ2つのアクションを選択すると、2つのアクションを区別できないため、エラーが発生します。

しかし、アクション選択ロジックを管理するための組み込み方法は、ActionMethodSelector classから派生した属性を使用することです。最初に、それから派生したクラスを作成します。このクラスにはアクションを呼び出すためのロジックが含まれています。パラメータがで を渡さGET registrationToken何 がなかった場合は、あなたの場合

では、それ以外の場合は、第二を使用することになり、パラメータなし 登録アクションを使用します。

public class RegistrationActionTokenAttribute : ActionMethodSelectorAttribute 
    { 
     public override bool IsValidForRequest(ControllerContext controllerContext, System.Reflection.MethodInfo methodInfo) 
     { 
      if (controllerContext.HttpContext.Request.QueryString.AllKeys.Contains("registrationToken")) 
      { 
       return true; 
      } 
      return false; 
     } 
    } 

クエリ文字列パラメータ「registrationToken」が含まれている場合、私は、2番目のアクションを選択するために有効とマークする必要があることを実演ロジックを実装しました。残ったものは、この属性を使って2番目のメソッドを飾ることです。

[RegistrationActionToken]  
public virtual ActionResult Register (Guid registrationToken) {...} 

エラーがなくなりました。さらにコントローラはクエリ文字列パラメータに応じて正しいアクションを選択するようになりました

+0

私は理論的にこの解決策が好きです。あなたがこれを行うことができるかどうかはわかりませんでしたが、これがメンテナンスの悪夢になることを恐れています。誰かが 'registrationToken'の名前を変更して属性を変更しないと、ユニットテストが容易ではないバグが発生します。 – KallDrexx

+0

アクション選択を制御する組み込みの方法です。一般に、属性コンストラクタでパラメータ名を渡すと、属性がアクションのパラメータに依存することがより明確になります – archil

+0

属性パラメータを使用してクエリ文字列を受け入れるように設定するのは良い点です。 – KallDrexx