4

プロジェクトには、BaseControllerという名前のコントローラーからすべて継承するコントローラーがいくつかあります。BaseControllerクラス全体に適用するカスタム属性を作成しました。これにより、いずれかのコントローラーでアクションが実行されるたびに、その属性が最初に実行されます。

問題は、その属性を無視したいコントローラーアクションがいくつかあることですが、その方法がわかりません。

誰か助けてもらえますか?私はMVC1を使用しています。

ありがとう。

4

3 に答える 3

12

カスタム属性に、次のようにこのShouldRun()チェックを追加できます。

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (ShouldRun(filterContext))
        {
            // proceed with your code
        }
    }

    private bool ShouldRun(ActionExecutingContext filterContext)
    {
        var ignoreAttributes = filterContext.ActionDescriptor.GetCustomAttributes(typeof(IgnoreMyCustomAttribute), false);
        if (ignoreAttributes.Length > 0)
            return false;

        return true;
    }

ShouldRun()は、アクションに「IgnoreMyCustomAttribute」があるかどうかをチェックするだけです。そこにある場合、カスタム属性は何もしません。

次に、何もしない単純なIgnoreMyCustomAttributeを作成します。

[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public class IgnoreMyCustomAttribute: ActionFilterAttribute
{
}

コントローラアクションを[IgnoreMyCustom]で装飾すると、MyCustomAttributeは何もしません。例えば:

[IgnoreMyCustom]
public ViewResult MyAction() {
}
于 2010-12-08T17:54:10.897 に答える
10

私はこのようなものを同様に必要としておりFilterAttribute, IAuthorizationFilter、通常のアクションフィルター(から派生)ではなく承認フィルター(実装/派生)を作成し、属性にActionFilterAttribute設定Inherited=trueAllowMultiple=falseて、適切な場所で1回だけ実行されることを発見しましたスポット。

これは、フィルターをベースコントローラー(サイト全体のデフォルト)から派生コントローラー(たとえば、AdminControllerなど)に、さらには個々のアクションメソッドに「カスケード」できることを意味します。

例えば、

[AttributeUsage(AttributeTargets.Class|AttributeTargets.Method, Inherited=true, AllowMultiple=false)]
public class MyCustomAttribute : FilterAttribute, IAuthorizationFilter
{
    private MyCustomMode _Mode;
    public MyCustomAttribute(MyCustomMode mode)
    {
        _Mode = mode;
    }
    public virtual void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }
        // run my own logic here.
        // set the filterContext.Result to anything non-null (such as
        // a RedirectResult?) to skip the action method's execution.
        //
        //
    }
}

public enum MyCustomMode
{
    Enforce,
    Ignore
}

そして、それを使用するために、スーパーコントローラーに適用できます。

[MyCustomAttribute(Ignore)]
public class BaseController : Controller
{
}

また、特定のコントローラー、または特定のアクションに対しても変更/オーバーライドできます。

[MyCustomAttribute(Enforce)]
public class AdministrationController : BaseController
{
    public ActionResult Index()
    {
    }

    [MyCustomAttribute(Ignore)] 
    public ActionResult SomeBasicPageSuchAsAHelpDocument()
    {
    }
}

これにより、特定の場合にフィルターを「オフ」にすることができ、コントローラー全体またはアプリケーション全体のいずれかにデフォルトとして適用することができました。

幸運を!

于 2011-02-21T19:15:42.820 に答える
3

この状況で属性を削除する簡単な方法があるかどうかはわかりません。しかし、私はプロジェクトに対して同様のことを行いました。属性を実行したくない場合はごくわずかであったため、2つの属性を作成することでした。

私の最初の属性はあなたが行ったように私のベースコントローラーに適用されましたが、2番目の属性の存在を認識しており、その2番目の属性を実装することで、基本クラスの属性の実行を無効にすることができました。

それが最善の解決策であったかどうかはわかりませんが、私にとってはうまくいきました。

これはベースコントローラーに適用されました:

/// <summary>
/// This is used to force the schema to HTTP is it is HTTPS.
/// RequireHttpsAttribute or OptionalHttpsAttribute takes precedence if used.
/// </summary>
public class RequireHttpAttribute : FilterAttribute, IAuthorizationFilter
{
    public virtual void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
            throw new ArgumentNullException("filterContext");

        if (filterContext.HttpContext.Request.IsSecureConnection)
        {
            object[] attributes = filterContext.ActionDescriptor.GetCustomAttributes(true);
            if (!attributes.Any(a => a is RequireHttpsAttribute || a is OptionalHttpsAttribute))
            {
                HandleHttpsRequest(filterContext);
            }
        }
    }

    protected virtual void HandleHttpsRequest(AuthorizationContext filterContext)
    {
        //  only redirect for GET method, otherwise browser may not propogate the verb and request body correctly
        if (!string.Equals(filterContext.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
            throw new InvalidOperationException(MvcResources.RequireHttpAttribute_MustNotUseSsl);

        //  redirect to HTTP version
        string url = "http://" + filterContext.HttpContext.Request.Url.Host + filterContext.HttpContext.Request.RawUrl;
        filterContext.Result = new RedirectResult(url);
    }
}

そのようです:

[RequireHttp]
public abstract class Controller : System.Web.Mvc.Controller
{
}

次に、事実上ダミー属性であるものを使用して、それを無効にすることができます。

/// <summary>
/// This attribute allows the action to be server on HTTP and HTTPS but neither is enforce.
/// RequireHttpsAttribute takes precedence if used.
/// </summary>
public class OptionalHttpsAttribute : FilterAttribute
{
    // This is deliberately empty, the attribute is used by RequireHttpAttribute to stop it changing schema to HTTP
}

そのようです:

    [OptionalHttps]
    public ActionResult OptionalHttps()
    {
        return View();
    }
于 2010-12-08T17:53:44.780 に答える