MVC4自定义OnActionExecuting Global.asx过滤器未被触发

时间:2013-01-26 19:48:24

标签: asp.net-mvc-4

我正在尝试创建一个全局过滤器,该过滤器将针对用户登录时的每个操作运行。根据我的阅读,有两个必要的步骤。首先,在Global.asx文件中添加新过滤器。

public class MvcApplication : System.Web.HttpApplication
{
    //I added this
    public static void RegisterGlobalFilters(GlobalFilterCollection filters)
    {
        filters.Add(new NotificationFilter());
    }
    protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();
        WebApiConfig.Register(GlobalConfiguration.Configuration);
        FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        BundleConfig.RegisterBundles(BundleTable.Bundles);
        AuthConfig.RegisterAuth();
    }
}

然后我必须在filters文件夹中创建过滤器。

public class NotificationFilter : ActionFilterAttribute 
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    { //Breakpoint here is never triggered
        //This code doesn't work, but it's what I want to do
        if (WebSecurity.CurrentUserId > 0)
        {
            var notificationCount = db.Notifications.GroupBy(i => i.UserID).Count();
            if (notificationCount > 99)
            {
                ViewBag.Notifications = "99+";
            }
            else
            {
                ViewBag.Notifications = notificationCount;
            }
        }
        base.OnActionExecuting(filterContext);
    }
}

我该如何使这项工作?有没有更好的办法?我可以将它添加到所有控制器,它可以工作,这不太理想。

4 个答案:

答案 0 :(得分:5)

我有同样的经历。您可以构建一个BaseController类并将过滤器定义放入其中。然后,所有控制器必须从BaseController类继承。因此,您不必在所有控制器中使用过滤器类。

类似的东西:

    public class BaseController : Controller
    {

        protected override void OnActionExecuting(ActionExecutingContext filterContext)
        {
         ...
         }
    }

在控制器中:

public class SampleController : BaseController
{
 ...
}

答案 1 :(得分:2)

您可以将此代码用于您的问题:

public class ParentController : Controller
{

   protected override void OnActionExecuting(ActionExecutingContext filterContext)
   {
       /* take current action*/
       action = (string)filterContext.RouteData.Values["action"];

       /* check if your action have your filter */
       if (!string.IsNullOrEmpty(action) && Methods.
                    Where(
                           method => method.Name == action
                           &&        method.GetCustomAttributes(typeof(/* your filter name */), true).Length > 0
                    ).Count() > 0)
          {
            // do your work    
          }


   }
}

public class YourController : ParentController 
{

  // implementation of your controller
}

答案 2 :(得分:1)

Jed,据我所知,您希望所有页面的行为方式相同,并为经过身份验证的用户呈现通知。

我建议你在你的_layout中放置一个左上角的Div和jquery Ajax调用(你可以稍后将jquery推送到alert.js文件中)。

    <div id='divNotifications'></div>

    <script type="text/javascript">
       $(document).ready(function() {
       $('#divNotifications').load('Notifications/UserNotifications');
       }
    </script>
通知控制器中的

具有返回的UserNotifications方法:

public JsonResult AjaxUserNotifications()
{

    Notifications Notifications = new GetNotifications();

    return Json(Notifications, JsonRequestBehavior.AllowGet);
}

首先,我建议您将此渲染一次作为功能的证明,然后我建议您将其作为定期调用。

How to constantly check for new message with setInterval without constantly notifying user?

这个堆栈线程进入如何使Ajax调用按时间间隔重复。

答案 3 :(得分:0)

一种可能的方法是使用小视图和SignalR进行推送通知。