MVC 中的 ActionFilter 和 Authorize 属性导致对象引用错误
ActionFilter and Authorize Attribute in MVC causing object reference error
我正在使用 MVC4
构建 ASP.NET
应用程序。我在我的业务逻辑中使用 ActionFilterAttribute
和 AuthorizeAttribute
。以下是示例代码
控制器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:
- Authorization filters
- Action filters
- Response filters
- 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 友好,也允许您通过以特定顺序全局注册过滤器来明确设置顺序。
我正在使用 MVC4
构建 ASP.NET
应用程序。我在我的业务逻辑中使用 ActionFilterAttribute
和 AuthorizeAttribute
。以下是示例代码
控制器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:
- Authorization filters
- Action filters
- Response filters
- 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 友好,也允许您通过以特定顺序全局注册过滤器来明确设置顺序。