2009-05-13 13 views
5

क्या नियंत्रक स्तर पर एक विशेषता जोड़ने का कोई तरीका है लेकिन एक विशिष्ट कार्रवाई पर नहीं। उदाहरण के लिए कहें कि मेरे पास मेरे नियंत्रक में 10 क्रियाएं थीं और केवल उन कार्रवाइयों में से एक को मेरे द्वारा बनाई गई विशिष्ट विशेषता की आवश्यकता नहीं है।नियंत्रकों और कार्यों पर एमवीसी गुण

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

    [Remove_MyAttribute] 
    public ActionResult Action3() {} 
} 

मैं संभवतः अन्य नियंत्रक में इस कार्रवाई को स्थानांतरित कर सकता है (लेकिन यह पसंद नहीं है) या मैं Action3 से छोड़ कर सभी कार्यों को MyAttribute लागू हो सकते हैं लेकिन सिर्फ अगर वहाँ एक आसान तरीका है सोचा है?

उत्तर

3

जोहान्स ने सही समाधान दिया और यहां बताया गया है कि मैंने इसे कैसे कोड किया ... उम्मीद है कि यह अन्य लोगों की सहायता करेगी।

 
[MyFilter("MyAction")] 
public class HomeController : Controller 
{ 
    public ActionResult Action1... 
    public ActionResult Action2... 
    public ActionResult MyAction... 
} 

public class CompressFilter : ActionFilterAttribute 
{ 
    private IList _ExcludeActions = null; 

    public CompressFilter() 
    { 
     _ExcludeActions = new List(); 
    } 

    public CompressFilter(string excludeActions) 
    { 
     _ExcludeActions = new List(excludeActions.Split(',')); 
    } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     HttpRequestBase request = filterContext.HttpContext.Request; 

     string currentActionName = (string)filterContext.RouteData.Values["action"]; 

     if (_ExcludeActions.Contains(currentActionName)) 
      return; 

     ... 
    } 
+0

धन्यवाद डेविड! वास्तव में मेरे मन में क्या था! –

2

आप इसे मुख्य विशेषता को पास करके एक विशिष्ट कार्रवाई को बाहर कर सकते:

[MyAttribute(Exclude="Action3")] 

संपादित

मेरे उदाहरण सिर से था (जैसा कि आप देख सकते हैं निम्नलिखित VB.NET है, हो सकता है कि यह गलत हो गया हो), इस प्रकार मैंने कार्यान्वित किया:

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

End Class 
3

आपको डिफ़ॉल्ट विशेषता को ओवरराइड/विस्तार करना और कस्टम कॉन जोड़ना है बहिष्करण की अनुमति देने के लिए संरक्षक। या आप बहिष्करण के लिए अपनी कस्टम विशेषता बना सकते हैं (आपके उदाहरण में [Remove_MyAttribute] है)।

+0

सही दिशा में बिंदु के लिए धन्यवाद। ive ने आपके उत्तर को ऊपर उठाया और फिर नीचे दिए गए मेरे उत्तर में समाधान प्रदान किया। – David

2

तुम क्या करने कोशिश कर रहे हैं के लिए सामान्य पैटर्न है और एक बूलियन पैरामीटर यदि विशेषता या लागू नहीं होती है इंगित करता है कि के साथ विशेषता है।

पूर्व:

[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) परिभाषित किया गया है, हालांकि जब मैं ईवेंट को डीबग करता हूं तो यह सही कन्स्ट्रक्टर कहता है कि मेरे गुण के अंदर निजी चर रीसेट हो रहा है। कोई विचार? – David

3

मैं जानता हूँ कि मेरा उत्तर एक छोटे से देर से (लगभग चार वर्ष) खेल के लिए है, लेकिन मैं इस सवाल में आए और मैं जिस समाधान को तैयार करता हूं उसे साझा करना चाहता था जो मुझे मूल प्रश्न करना चाहता था, अगर भविष्य में किसी और की मदद करता है।

समाधान में 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... 

} 

मुझे आशा है कि इस संकलित, मैं कुछ इसी तरह के कोड से यह yanked और एक छोटे से रों किया इस पर earch-and-replace ताकि यह सही नहीं हो सकता है।

+0

पीएस, मेरी राय में इस दृष्टिकोण के साथ लाभ, जिसे मैं स्पष्ट रूप से अवगत कराने के लिए भूल गया था, यह है कि आपके पास एक्शन नामों का प्रतिनिधित्व करने वाले जादू तार नहीं हैं, और न ही मैपिंग को सब कुछ के शीर्ष पर अद्यतित रखने की याद रखने की आवश्यकता है : जैसे ही आप जाते हैं, वैसे ही आप सजाने के रूप में सजाने के लिए इग्नोर/सम्मान स्विच को आगे बढ़ाते हैं। सौभाग्य! – Funka

+0

वंशावली के लिए: यह भी देखें http://stackoverflow.com/questions/4390541/asp-net-mvc-ignore-custom-attribute-in-a-base-controller-class/5070193#5070193 – Funka

संबंधित मुद्दे