Action Filter to check Session MVC3

2019-06-06 23:44发布

问题:

I want to create some custom Filters in my application

After successful login i keep logged in user details in a session and want to check the session is expired or not ( If session expired i want to redirect to login page) and i need a filter for this.

  public class MyActionFilterAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        SchoolApp.ViewModels.CurrentSessionModel  model=(SchoolApp.ViewModels.CurrentSessionModel)HttpContext.Current.Session["mySession"];
        if (model == null)
        {
          //Redirect to Login page 
        }
        else
        {
            base.OnActionExecuting(filterContext);
        }
    }
}

But the problem is this will fire for every rquests even while loading Login page . So how can i make a useful filter control that check for session

回答1:

Looks like you're trying to do wrong things there. Check your web.config file - it should have section like:

<authentication mode="Forms">
  <forms loginUrl="http://www.your_domain.com/login" name="cookie_name" defaultUrl="default_url" domain="your_domain" enableCrossAppRedirects="true" protection="All" slidingExpiration="true" cookieless="UseCookies" timeout="1440" path="/" />
</authentication>

If your session is expired (cookie with cookie_name non exists anymore) - user will be automatically redirected to loginUrl

If you still want to use filters - there's solution that allows you to exclude global filter for some controllers/actions:

assuming you have method in global.asax.cs:

private static void RegisterGlobalFilters(GlobalFilterCollection filters)
{
    IFilterProvider[] providers = FilterProviders.Providers.ToArray();
    FilterProviders.Providers.Clear();
    FilterProviders.Providers.Add(new ExcludeFilterProvider(providers));

    filters.Add(DependencyResolver.Current.GetService<MyFilter>(), 2); // add your global filters here
}

Call it in your global.asax.cs:

RegisterGlobalFilters(GlobalFilters.Filters);

Filter provider class will look like:

public class ExcludeFilterProvider : IFilterProvider
{
    private readonly FilterProviderCollection _filterProviders;

    public ExcludeFilterProvider(IFilterProvider[] filters)
    {
        _filterProviders = new FilterProviderCollection(filters);
    }

    public IEnumerable<Filter> GetFilters(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
    {
        Filter[] filters = _filterProviders.GetFilters(controllerContext, actionDescriptor).ToArray();
        if (filters.Select(f => f.Instance).OfType<OverrideExcludeFilter>().Any())
            return filters;
        IEnumerable<ExcludeFilterAttribute> excludeFilters = (from f in filters where f.Instance is ExcludeFilterAttribute select f.Instance as ExcludeFilterAttribute);
        var excludeFilterAttributes = excludeFilters as ExcludeFilterAttribute[] ?? excludeFilters.ToArray();
        if (excludeFilterAttributes.FirstOrDefault(f => f.AllFilters) != null)
        {
            return new Collection<Filter>();
        }

        var filterTypesToRemove = excludeFilterAttributes.SelectMany(excludeFilter => excludeFilter.FilterTypes);
        IEnumerable<Filter> res = (from filter in filters where !filterTypesToRemove.Contains(filter.Instance.GetType()) select filter);
        return res;
    }
}

ExcludeFilter attribute class:

public class ExcludeFilterAttribute : FilterAttribute
{
    private readonly Type[] _filterType;

    public ExcludeFilterAttribute(bool allFilters)
    {
        AllFilters = allFilters;
    }

    public ExcludeFilterAttribute(params Type[] filterType)
    {
        _filterType = filterType;
    }

    /// <summary>
    /// exclude all filters
    /// </summary>
    public bool AllFilters { get; private set; }

    public Type[] FilterTypes
    {
        get
        {
            return _filterType;
        }
    }
}

And usage sample:

    [ExcludeFilter(new[] { typeof(MyFilter) })]
    public ActionResult MyAction()
    {
        //some codes
    }

So this way your filter of type MyFilter won't fire for specified action