【问题标题】:MVC Custom Action AttributeMVC 自定义操作属性
【发布时间】:2011-09-21 18:59:39
【问题描述】:

在测试期间(至少),我们为每个控制器/动作记录了一些低级信息。所有控制器都派生自我们自定义的 BaseController,它会覆盖 OnActionExecuting 来进行日志记录。

我们在 BaseController 中有一个属性来确定是否会发生此日志记录,以便控制器可以覆盖 OnActionExecuting 自身,重置标志,然后调用“base.OnActionExecuting”。该标志通常为真,但我们希望为某些 Json 请求关闭它。

我们更愿意创建一个自定义控制器/动作过滤器来处理它,如下所示:

[LogPageAccess(false)]
[HttpGet]
Public ActionResult Foobar()

我确定有办法做到这一点,但我无法弄清楚如何创建自定义属性并让它在 BaseController 中重置标志。

谢谢...

【问题讨论】:

    标签: asp.net-mvc-3 attributes controller action


    【解决方案1】:

    在我的项目中,我使用以下方法来验证访问控制器:

        [Capability(UserCapability.FileManagement)]
        public ActionResult FileList(FileListRequestModel request, bool ajax = false)
        {
            //code
        }
    

    这是我的能力等级

    /// <summary>
    /// Decorator to MVC class and method to evaluate if a certain capability is enabled
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class CapabilityAttribute : AuthorizeAttribute
    {
        #region Class Attributes
    
        private object _capability = null;
    
        #endregion
    
        #region Public Methods
    
        /// <summary>
        /// Create a new capability attribute
        /// </summary>
        /// <param name="capability">Context Value passed to the validator</param>
        public CapabilityAttribute(object capability)
        {
            this._capability = capability;
        }
    
        /// <summary>
        /// Check if attribute is enabled
        /// </summary>
        /// <param name="filterContext"></param>
        public override void OnAuthorization(AuthorizationContext filterContext)
        {
            if (!Capability.Enabled(this._capability))
            {
                throw new UnauthorizedAccessException();
            }
            else
            {
                base.OnAuthorization(filterContext);
            }
        }
    
        #endregion
    }
    

    您只需要根据您的情况调整此代码,我希望它变得有用

    【讨论】:

    • 需要类似的东西,这让我到达了我需要去的地方。但是,我没有使用UnauthorizedAccessException,而是使用了filterContext.Result = new HttpUnauthorizedResult();,我觉得它更适合MVC页面。您可以查看the MSDN documentation for UnauthorizedAccessException 以了解为什么我觉得它不适合这种情况。
    【解决方案2】:

    我尝试构建一个简单的例子来说明你的情况,但后来意识到我无法将实例数据传递给Attribute--所以假设我将Log 标志设置为false ,我不能用它来直接操作基本控制器的属性。

    Check out this SO post.

    这是我正在玩的代码(无法编译——无法通过this):

    public class BaseController : Controller
    {
        public bool LogPageRequests { get; set; }
    }
    
    public class LogPageAccess : ActionFilterAttribute
    {
        public LogPageAccess(BaseController baseController, bool log = true)
        {
            baseController.LogPageRequests = log;
        }
    
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            //Do Whatever
            base.OnActionExecuting(filterContext);
        }
    }
    
    public class SomeController : BaseController
    {
        [LogPageAccess(this, false)]
        public ActionResult Index()
        {
            return View();
        }
    }
    

    也许你可以通过反射来做一些事情,但你可能不得不按照你一直在做的方式来做这件事,因为似乎不可能将实例数据获取到属性中。

    【讨论】:

    • 可以从上下文中获取控制器。
    • @SLaks 你能给我一个快速而肮脏的例子吗?
    • 我尝试了filterContext.Controller,但这并不能访问它的属性(在我的原始示例中为LogPageRequests)。我最终做的是创建一个AuthorizeAttribute,然后在TempData 中设置一个标志,我在BaseController 中签入OnActionExecuting。绝对做作,但它似乎确实有效。
    猜你喜欢
    • 2021-06-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-03
    • 1970-01-01
    相关资源
    最近更新 更多