2009-05-13 40 views
5

Có cách nào để thêm Thuộc tính trên cấp Bộ điều khiển nhưng không phải trên một hành động cụ thể. Ví dụ: nếu tôi có 10 Hành động trong Bộ điều khiển của tôi và chỉ 1 trong số các Tác vụ đó không yêu cầu thuộc tính cụ thể mà tôi đã tạo.Thuộc tính MVC trên Bộ điều khiển và Hành động

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

    [Remove_MyAttribute] 
    public ActionResult Action3() {} 
} 

Tôi có thể di chuyển hành động này vào bộ điều khiển khác (nhưng không thích điều đó) hoặc tôi có thể áp dụng MyAttribute cho tất cả các hành động ngoại trừ Action3 nhưng chỉ nghĩ là có cách nào dễ hơn?

Trả lời

3

Johannes đã đưa ra giải pháp đúng và đây là cách tôi mã hóa nó ... hy vọng nó sẽ giúp người khác.

 
[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

Cảm ơn David! Chính xác những gì tôi đã có trong tâm trí! –

2

Bạn có thể loại trừ một hành động cụ thể bằng cách đi qua nó để thuộc tính chính:

[MyAttribute(Exclude="Action3")] 

EDIT

dụ của tôi là từ đầu (như bạn có thể thấy đây là VB.NET, có thể đó là nơi xảy ra sự cố), đây là cách tôi đã triển khai:

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

End Class 
3

Bạn phải ghi đè/mở rộng thuộc tính mặc định và thêm con tùy chỉnh structor để cho phép loại trừ. Hoặc bạn có thể tạo thuộc tính tùy chỉnh của bạn để loại trừ (trong ví dụ của bạn là [Remove_MyAttribute]).

+0

cảm ơn cho điểm đi đúng hướng. ive upvoted câu trả lời của bạn sau đó cung cấp các giải pháp trong câu trả lời của tôi dưới đây. – David

2

Mẫu thông thường cho những gì bạn đang cố làm là có và thuộc tính với tham số boolean cho biết thuộc tính có được áp dụng hay không.

Ex:

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

or 

[ComVisible(false)] 

inf trường hợp của bạn, bạn sẽ có:

[MyAttribute] // defaults to true 

and 

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

Vì vậy, bạn xác định nó ở cấp điều khiển sau đó có hiệu quả ghi đè lên hành động chính nó ... tôi thích ý tưởng đó và là đơn giản hơn so sánh nó với tên hành động. cảm ơn cho giải pháp của bạn. – David

+0

Tôi đang sử dụng RenderAction từ một phương thức trình trợ giúp mà MyAttribute (false) được định nghĩa tuy nhiên khi tôi gỡ lỗi eventhough nó gọi đúng constructor biến private bên trong thuộc tính của tôi tiếp tục được thiết lập lại. Bất kỳ ý tưởng? – David

3

Tôi biết câu trả lời của tôi là một chút muộn (gần bốn năm) để các trò chơi, nhưng tôi đã xem qua câu hỏi này và muốn chia sẻ một giải pháp mà tôi nghĩ ra, cho phép tôi làm rất nhiều điều mà câu hỏi ban đầu muốn làm, trong trường hợp nó giúp mọi người trong tương lai.

Giải pháp liên quan đến một viên đá quý nhỏ được gọi là AttributeUsage, cho phép chúng tôi chỉ định thuộc tính trên bộ điều khiển (và thậm chí bất kỳ bộ điều khiển cơ sở nào) và sau đó ghi đè lên (bỏ qua/loại bỏ) trên từng hành động hoặc bộ điều khiển phụ. Chúng sẽ "xếp" xuống đến nơi mà thuộc tính chi tiết nhất thực sự cháy: tức là chúng đi từ các bộ điều khiển cơ sở (cụ thể) đến các bộ điều khiển có nguồn gốc cụ thể hơn (các phương thức hành động).

Đây là cách:

[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 
} 

(Tôi nghe nói bạn như thuộc tính, vì vậy tôi đặt một số thuộc tính trên thuộc tính Đó là thực sự những gì làm cho công việc kỳ diệu ở đây tại rất đầu: Cho phép họ để kế thừa/tầng, nhưng chỉ cho phép một trong số họ để thực hiện)

Sau đây là cách nó được sử dụng tại:.

[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... 

} 

tôi hy vọng điều này biên dịch, tôi giật nó từ một số mã tương tự và đã làm một chút s earch và thay thế nó để nó có thể không hoàn hảo.

+0

PS, lợi thế với cách tiếp cận này theo ý kiến ​​của tôi, mà tôi quên nói rõ ràng, là bạn không có chuỗi ma thuật đại diện cho tên hành động, cũng không cần phải giữ bản đồ luôn cập nhật ở đầu mọi thứ : bạn chỉ cần trang trí như bạn đi, lật chuyển đổi Bỏ qua/Tôn trọng qua lại khi cần thiết hơn nữa xuống bạn đi. Chúc may mắn! – Funka

+0

Đối với hậu thế: Xem thêm http://stackoverflow.com/questions/4390541/asp-net-mvc-ignore-custom-attribute-in-a-base-controller-class/5070193#5070193 – Funka

Các vấn đề liên quan