简体   繁体   中英

How IAclModule works

I want to know how exactly this class IAclModule works, I mean the process it pass, it's instanceaded one each loop to verify the access for the user, or it's used the same instance each time?

I ask that because I need to implement my own logic since the default AuthorizeAttributeAclModule and XmlRolesAclModule have been wayyy to slow.

Thx.

The AclModule is instantiated by the DI (dependency injection) container. When using the internal DI container, it is instantiated by the SiteMapFactoryContainer.ResolveAclModule method . However, whether using internal or external DI, the instance is kept alive for the lifetime of the SiteMap object (and therefore by the cache) by being stored in a private field of the SiteMapPluginProvider class, which in turn is in a private field of the SiteMap class. Therefore, there is 1 instance per SiteMap which by default only gets created each time the cache expires (1 time every 5 minutes by default).

The AuthorizeAttributeAclModule has been tested pretty thoroughly and has been optimized pretty well. However, it creates an instance of the related controller class and the AuthorizeAttribute class for each node , so if your Controllers or any custom implementations of AuthorizeAttribute are doing too much work in the constructor, you could run into performance issues.

To fix this, you should aim to inject dependencies into each controller through the Controller constructor instead of doing heavy lifting inside of the constructor. If you use a dependency injection container in conjunction with a custom IControllerFactory , you can control the lifetime of the dependencies externally from the controller. As shown in the example below, when using this approach you could use the same instance of IMyRepository for every instance of MyController.

public class MyController : Controller
{
    public MyController(IMyRepository repository)
    {
        if (repository == null)
            throw new ArgumentNullException("repository");
        this.repository = repository;
    }
    private readonly IMyRepository repository;

    public ActionResult Index()
    {
        var items = this.repository.GetList()

        return View(items);
    }
}

That is a recommended best practice for the design of your controllers, but in a pinch, you could also request-cache your dependencies if they are expensive to create so each controller instance won't be so time-consuming to create if it is instatiated more than one time per request.

public class MyController : Controller
{
    public MyController()
    {
        this.repository = this.GetOrCreateRepository();
    }
    private readonly IMyRepository repository;

    private IMyRepository GetOrCreateRepository()
    {
        var key = "MyControllerRepository";
        var result = HttpContext.Items[key];
        if (result == null)
        {
            // If the expensive dependency wasn't already created for this request, do it now
            result = new MyRepository();

            // Save the instance in the request, so the next time this controller is created,
            // it doesn't have to instantiate it again.
            HttpContext.Items[key] = result;
        }
        return result;
    }

    public ActionResult Index()
    {
        var items = this.repository.GetList()

        return View(items);
    }
}

Also, if you have custom AuthorizeAttribute(s) you should make sure they are not doing any work except checking whether the user is authorized, delegating the real work to a handler the same way that Microsoft does.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM