2009-05-13 14 views
5

の属性。たとえば、コントローラに10個のアクションがあり、それらのアクションのうち1個だけが作成した特定の属性を必要としないとします。MVCは、コントローラレベルではなく、具体的なアクションに属性を追加する方法はありコントローラとアクション

 
[MyAttribute] 
public class MyController : Controller 
{ 
    public ActionResult Action1() {} 
    public ActionResult Action2() {} 

    [Remove_MyAttribute] 
    public ActionResult Action3() {} 
} 

私は潜在的に別のコントローラにこのアクションを移動し(それを好まない)、または私はAction3から除いたすべてのアクションにMyAttributeを適用することができますが、もっと簡単な方法があるかどうかだけ考えただろうか?

答えて

3

ヨハネスは、正しい解決策を与え、ここで私はそれをコード化する方法...それは他の人の役に立てば幸いです。

+0

ありがとうDavid!まさに私が思いついたこと! –

2

あなたはメイン属性に渡すことで特定のアクションを除外することができます:あなたは、以下のVB.NETで見ることができるよう

[MyAttribute(Exclude="Action3")] 

EDIT

私の例では、(頭からでしたそれは間違っていたところ、多分それは)ですが、これは私が実装方法です:

<Models.MyAttribute(Exclude:="Action3")> _ 
Public Class MyController 
Inherits System.Web.Mvc.Controller 

End Class 
3

あなたは/上書きデフォルト属性を拡張し、カスタムコンを追加する必要があります除外を許可する構造体。または、除外のカスタム属性を作成することもできます(この例では[Remove_MyAttribute])。

+0

正しい方向のポイントに感謝します。あなたの答えをアップアップし、私の答えで解決策を提供した。 – David

2

あなたがしようとしている通常のパターンは、属性が適用されているかどうかを示すbooleanパラメータを持つことです。

例:

[ComVisible] which is equivalent with [ComVisible(true)] 

or 

[ComVisible(false)] 

は、あなたが持っているでしょう、あなたのケースをINF]

[MyAttribute] // defaults to true 

and 

[MyAttribute(false)] for applying the attribute on excluded members 
+0

コントローラレベルで定義し、アクション自体を効果的にオーバーライドします。そのアイデアは好きで、アクション名と比較するよりも簡単です。あなたのソリューションに感謝します。 – David

+0

MyAttribute(false)が定義されているHelperメソッドからRenderActionを使用していますが、実際のコンストラクタを呼び出すのにイベントをデバッグするときに、自分の属性のprivate変数がリセットされたままになります。何か案は? – David

3

私は私の答えは、ゲームに(ほぼ4年)少し遅れているけど、私はこの質問に出くわしました私が考案した解決策を共有したいと思っていました。これは、元の質問が今後どのような人に役立つかについて、何をしたいのかとほとんど変わりません。

ソリューションは、必要に応じて、私たちは、個々のアクションまたはサブコントローラ上で(無視する/削除)(!とでも任意の塩基コントローラ)コントローラの属性を指定して上書きすることができますAttributeUsageと呼ばれる小さな宝石を伴います。最も細分化されたアトリビュートのみが実際に起動する場所、つまり、最小限の固有の(ベースコントローラ)から、より特定の(派生したコントローラへ)、最も特定の(アクションメソッド)まで、「カスケード」します。

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method, Inherited=true, AllowMultiple=false)] 
public class MyCustomFilterAttribute : ActionFilterAttribute 
{ 

    private MyCustomFilterMode _Mode = MyCustomFilterMode.Respect;  // this is the default, so don't always have to specify 

    public MyCustomFilterAttribute() 
    { 
    } 
    public MyCustomFilterAttribute(MyCustomFilterMode mode) 
    { 
     _Mode = mode; 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     if (_Mode == MyCustomFilterMode.Ignore) 
     { 
      return; 
     } 

     // Otherwise, respect the attribute and work your magic here! 
     // 
     // 
     // 
    } 

} 

public enum MyCustomFilterMode 
{ 
    Ignore = 0, 
    Respect = 1 
} 

(私は属性のようにあなたを聞いたので、私は属性にいくつかの属性を置くことは非常に先頭にここに魔法の仕事を作るものは本当にです:

はここにどのようにだ!彼らは/カスケードを継承できるように、しかし、それらの一方のみが実行できるようにする)

ここではそれが使用されるようになりました方法は次のとおりです。

[MyCustomFilter] 
public class MyBaseController : Controller 
{ 
    // I am the application's base controller with the filter, 
    // so any derived controllers will ALSO get the filter (unless they override/Ignore) 
} 

public class HomeController : MyBaseController 
{ 
    // Since I derive from MyBaseController, 
    // all of my action methods will also get the filter, 
    // unless they specify otherwise! 

    public ActionResult FilteredAction1... 
    public ActionResult FilteredAction2... 

    [MyCustomFilter(Ignore)] 
    public ActionResult MyIgnoredAction... // I am ignoring the filter! 

} 

[MyCustomFilter(Ignore)] 
public class SomeSpecialCaseController : MyBaseController 
{ 
    // Even though I also derive from MyBaseController, I can choose 
    // to "opt out" and indicate for everything to be ignored 

    public ActionResult IgnoredAction1... 
    public ActionResult IgnoredAction2... 

    // Whoops! I guess I do need the filter on just one little method here: 
    [MyCustomFilter] 
    public ActionResult FilteredAction1... 

} 

、私はいくつかの類似したコードからそれをヤンクし、少しのをやった、これはコンパイルを願ってearch-and-replaceで完璧ではないかもしれません。

+0

PS、私が明示的に述べることを忘れてしまった私の意見では、このアプローチの利点は、アクション名を表す魔法の文字列を持たず、マッピングを常に最新の状態に保つ必要がないことですあなたが行くにつれて飾るだけで、Ignore/Respectスイッチを必要に応じて前後にずらして前後にずらしています。がんばろう! – Funka

+0

後生用:http://stackoverflow.com/questions/4390541/asp-net-mvc-ignore-custom-attribute-in-a-base-controller-class/5070193#5070193も参照してください。 – Funka

関連する問題