Best place to locate filters in MVC n-layer web application and should I use services/repositories in them? I am a little confused over which layers my filters should be contained in with an n-layer web application.

I've got 4 layers:


Presentation layer
Application layer
Business layer
Infrastructure layer


The Presentation layer can only talk to the Application layer and the Infrastructure layer. The Application layer can only talk to the Presentation layer, Business layer and the Infrastructure layer. The Business layer can only talk to the Application layer and the Infrastructure layer.

All my models, views and controllers are stored in the Presentation layer.

I have the following code:

public class AuthoriseAttribute : AuthorizeAttribute
{
    public override void OnAuthorization(AuthorizationContext filterContext)
    {
        if (filterContext == null)
        {
            throw new ArgumentNullException("filterContext");
        }

        if (SkipAuthorisation(filterContext))
        {
            return;
        }

        // This line...
        var evalReportProxy = new EvalReportProxy(WebHelper.PcwAliasName);
        if (evalReportProxy.EvalReport.SubscribedToModule("Workspace Only"))
        {
            filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary 
            { 
                { "controller", "Redirect" },
                { "action", "Workspace" }
            });
        }

        if (string.IsNullOrEmpty(WebHelper.Username) || WebHelper.IsGuest)
        {
            filterContext.Result = new RedirectToRouteResult(
            new RouteValueDictionary 
            { 
                { "controller", "Account" },
                { "action", "LogIn" }
            });
        }
    }

    private static bool SkipAuthorisation(AuthorizationContext filterContext)
    {
        return filterContext.ActionDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true)
            || filterContext.ActionDescriptor.ControllerDescriptor.IsDefined(typeof(AllowAnonymousAttribute), inherit: true);
    }
}


I've highlighted a line of code using a comment which shows where I am making use of a concrete type in the infrastructure layer to check to see if a user is subscribed to a module. By using a concrete type I've made it impossible to use mock objects which I want to avoid, but...

I'm a little confused because in the line highlighted using a comment I guess I should really be using a repository or a service although I'm not really sure if I should be or not. Also, if I use a repository then the filters can't be in the presentation layer, but I'm not sure if services are purely for controllers or whether I can use services elsewhere.

Can anyone please advise me on whether I should be putting filters in the presentation layer or not, and whether or not I should be using a service, repository, or keep the code how it is.

Also, I'm open to code improvements if you think any can be made.
Here's my take on this problem.

Your use of the AttributeFilter in the presentation layer is fine. You are correct about avoiding the use of a Repository in the filter, it does not belong there. However you can call upon the business layer (which in turn calls your repository) to check if they are subscribed. Keep your business logic where it belongs.

Dependencies in Filters can be mocked, you simply need to create a constructor which accepts the IBusinessService of your choice. Most dependency injection frameworks will create Filters and pass in the correct dependency.

If you don't want to go down that route, change your Filter like so.

class AuthoriseAttribute {

  // Use for testing
  public AuthoriseAttribute(IMockedBusinessService) {
  }

  // Production
  public AuthoriseAttribute():this(new ConcreteBusinessService()) {
  }
}


As always with these things, "it depends". If you have a high performance site, say > 200 connections per second and you get considerable performance gains by having the repository in directly in the presentation layer, then I would bend the rules and leave a nice comment in the code on why you have data access in the presentation layer.

Almost always I prefer code readability and separation of concerns much higher than anything else. Just be sure to take measurements on the performance gains by doing X. If your not measuring, your guessing.