orchardcmsorchardcms-1.9

Where should I put code that I want to always run for each request?


Maybe this is more of an ASP.NET MVC question than an Orchard question but I'm relatively new to both and I don't know the answer in either case.

ASP.NET MVC applications don't technically have a single point of entry, so where am I supposed to put code that I want to always run each and every time someone visits any page, regardless of layer or origin or permissions? Is there a specific Orchard way of doing this?

If it makes a difference, what I'm specifically trying to do at the moment is to restrict the IP range that has access to my website. I want to look at every incoming request and check if the user is either authenticated or has an IP in the allowed range that I configured in my custom settings.

I can think of some quick and dirty ways to achieve this like putting the check in Layout and wrap a condition around all of my zones or implement IThemeSelector to switch to a different Theme but I'd like to do it properly.


Solution

  • All what should you do to achieve this, is implementing new IActionFilter or IAuthorizationFilter like the following:

    public class CheckAccessFilter : FilterProvider, IActionFilter, IAuthorizationFilter {
        public void OnActionExecuting(ActionExecutingContext filterContext) {
            // here you can check the incoming request, and how the system will deal with it,
            // before executing the action
        }
    
        public void OnActionExecuted(ActionExecutedContext filterContext) {
    
        }
    
        public void OnAuthorization(AuthorizationContext filterContext) {
            // here you can authorize any request
        }
    }
    

    But if you want only to authorize based on content items (like: Widgets, Pages, Projections), you can implement IAuthorizationServiceEventHandler:

    public class IPAuthorizationEventHandler : IAuthorizationServiceEventHandler {
        public void Checking(CheckAccessContext context) { 
        }
    
        public void Adjust(CheckAccessContext context) { 
        }
    
        public void Complete(CheckAccessContext context) { 
        }
    }
    

    The best sample you can follow to implement this approach is SecurableContentItemsAuthorizationEventHandler, you can find it in Orchard.ContentPermissions module.