c#MVC站点地​​图 - 使用角色时非常慢 - 非常慢

时间:2015-07-09 14:03:04

标签: mvcsitemapprovider

我已经为MVC5安装了MVC站点地​​图提供程序,并且只使用了所有内容。它工作正常。现在我想实现基于菜单修剪的角色,所以假设我的控制器:

public class Home: Controller
{

    [Authorize(Roles="Admin")]
    public ActionResult Index()
    {
        return View();
    }
}

现在基本上只有Admin角色的用户才能看到菜单。完美无瑕。

同样为了实现这一点,我在web.config中添加了这一行:

  <add key="MvcSiteMapProvider_SecurityTrimmingEnabled" value="true" />

问题在于它有效,但速度很慢。加载页面大约需要7秒钟。如果我删除了web.config行,基本上删除了基于角色的菜单修剪,它需要大约300毫秒才能加载页面。这里出了点问题。

为什么我的菜单修剪基于角色的想法很慢?我没有做任何自定义。

2 个答案:

答案 0 :(得分:0)

虽然发布了Route values not preserved correctly in v4?

的错误

但看起来它已在下一版本的第4版修复。

修复此问题的另一种解决方法是此处的缓存是一篇相关文章。

MVC siteMap provider cache

答案 1 :(得分:0)

安全修整功能依赖于为每个节点创建一个控制器实例,以确定当前用户上下文是否具有访问权限。

这种缓慢的最可能原因是你的控制器(或它们的基类)在构造函数中发生了太多繁重的处理。

public class HomeController
{
    public HomeController() {
        // Lots of heavy processing
        System.Threading.Thread.Sleep(300);
    };
}

上面的示例将为表示HomeController中的操作方法的每个节点的页面加载时间添加300毫秒。如果您的其他控制器在实例化期间也有大量处理,它们还会为每个页面加载添加额外的时间。

遵循DI最佳实践时,这不是问题,因为在创建控制器实例后,外部服务会发生繁重的处理。

public interface IHeavyProcessingService
{
    IProcessingResult DoSomethingExpensive();
}

public class HeavyProcessingService : IHeavyProcessingService
{
    public HeavyProcessingService() { 
    }

    public IProcessingResult DoSomethingExpensive() {
        // Lots of heavy processing
        System.Threading.Thread.Sleep(300);
    }
}

public class HomeController
{
    private readonly IHeavyProcessingService heavyProcessingService;

    // The constructor does no heavy processing. It is deferred until after
    // the instance is created by HeavyProcessingService. 
    // The only thing happening here is assignment of dependencies.
    public HomeController(IHeavyProcessingService heavyProcessingService) {

        if (heavyProcessingService == null)
            throw new ArgumentNullException("heavyProcessingService");

        this.heavyProcessingService = heavyProcessingService;
    };

    public ActionResult Index()
    {
        var result = this.heavyProcessingService.DoSomethingExpensive();

        // Do something with the result of the heavy processing

        return View();
    }

    public ActionResult About()
    {
        return View();
    }

    public ActionResult Contact()
    {
        return View();
    }
}

请注意,在上面的示例中,构造函数中没有发生繁重的处理?这意味着创建HomeController的实例非常便宜。这也意味着不需要进行繁重处理的操作方法(如示例中的About()Contact())不会受到{所需的繁重处理的影响。 {1}}。

如果不使用DI,MVC仍然需要为每个请求创建一个新的控制器实例(控制器实例永远不会在用户或操作方法之间共享)。虽然,在这种情况下,它并不像每个用户那样明显,因为每个用户只创建了一个实例。基本上,由于您的应用程序已存在问题(您现在可以修复),Index()正在放慢速度。

即使您没有使用DI,在创建控制器实例之前,仍然是延迟重度处理的最佳做法。

MvcSiteMapProvider

但是,如果不能在应用程序中将大量处理移动到外部服务中,则仍然可以通过将处理移动到另一个方法来将处理推迟到需要处理,因此创建控制器实例并不太昂贵。

public class HomeController
{
    private readonly IHeavyProcessingService heavyProcessingService;

    public HomeController() {

        this.heavyProcessingService = new HeavyProcessingService();
    };

    public ActionResult Index()
    {
        var result = this.heavyProcessingService.DoSomethingExpensive();

        // Do something with the result of the heavy processing

        return View();
    }
}