MVC 中的 ActionFilter 和 Authorize 属性导致对象引用错误

ActionFilter and Authorize Attribute in MVC causing object reference error

我正在使用 MVC4 构建 ASP.NET 应用程序。我在我的业务逻辑中使用 ActionFilterAttributeAuthorizeAttribute。以下是示例代码

控制器Class

[SessionExpire]
[AuthorizeSubscription]
public class StoreController : Controller
{
    public ActionResult StoreDetail()
    {
       // My logic goes here
    }

    [AuthorizeProductEdit]
    [HttpGet]
    public ActionResult EditProduct()
    {
       // My logic goes here
    }

如果我们看一下代码,我首先使用了继承 ActionFilterAttribute class 的 SessionExpire 属性,它检查 session 是否对当前请求有效并执行那里有一些重定向。接下来,我正在检查继承 AuthorizeAttribute class 的 AuthorizeSubscription 属性。它还根据那里写的逻辑做一些重定向。

EditProduct动作中,我用了另一个AuthorizeAttribute

如果我点击 url 进行 StoreDetail 操作而没有进行任何 session,它会将我重定向到所需的页面。

但是如果我点击 url 进行 EditProduct 操作,它会抛出我 Object Reference error。在调试期间,它首先进入 AuthorizeProdcutEdit 的代码,但找不到 Session Null。

为什么它不首先执行 SessionExpire 代码,如果找到 Session Null 则退出?

根据MSDN,过滤属性的顺序首先由其类型(例如授权过滤器、动作过滤器等​​)确定,然后由其范围(例如控制器范围、动作范围)确定。

您的 SessionExpire 属性的类型为 Action,范围为 Controller。 您的 AuthorizeProductEdit 属性的类型为 Authorization,范围为 Action。

这就是为什么您的 AuthorizeProductEdit 属性最先出现的原因。

来自documentation(我的重点)

The ASP.NET MVC framework supports four different types of filters:

Authorization filters – Implements the IAuthorizationFilter attribute.

Action filters – Implements the IActionFilter attribute.

Result filters – Implements the IResultFilter attribute.

Exception filters – Implements the IExceptionFilter attribute.

Filters are executed in the order listed above. For example, authorization filters are always executed before action filters and exception filters are always executed after every other type of filter.

根据 MSDN:

Filters run in the following order:

  1. Authorization filters
  2. Action filters
  3. Response filters
  4. Exception filters

你的 SessionExpire 属性在你的 AuthorizeSubscription 属性之后触发的原因是因为 MVC 总是首先触发授权过滤器。

因此,要解决该问题,您需要 SessionExpire 来实现 IAuthorizationFilter(并且可能会继承 Attribute)。

此外,您将需要 set the order of your attributes,因为 .NET 框架不保证它们的处理顺序。

[SessionExpire(Order=1)]
[AuthorizeSubscription(Order=2)]
public class StoreController : Controller
{
   // Remaining implementation...

请注意,最好的方法是 separate your filters from your attributes,这既允许它们对 DI 友好,也允许您通过以特定顺序全局注册过滤器来明确设置顺序。