【问题标题】:c# MVC Site Map - very slow when using roles - very slowc# MVC Site Map - 使用角色时非常慢 - 非常慢
【发布时间】:2015-07-09 14:03:04
【问题描述】:

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

public class Home: Controller
{

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

现在基本上只有管理员角色的用户可以看到菜单。完美效果很好。

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

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

问题是它可以工作,但速度很慢。页面加载大约需要 7 秒。如果我删除 web.config 行,基本上会根据角色删除菜单修剪,页面加载需要大约 300 毫秒。这里有问题。

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

【问题讨论】:

    标签: mvcsitemapprovider


    【解决方案1】:

    虽然Route values not preserved correctly in v4? 发布了一个错误

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

    解决此问题的另一种解决方法是缓存这里是相关文章。

    MVC siteMap provider cache

    【讨论】:

      【解决方案2】:

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

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

      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())不会受到Index() 所需的繁重处理的影响。

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

      即使您不使用 DI,最好将繁重的处理推迟到创建控制器实例之后。

      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();
          }
      }
      

      但是,如果不能将繁重的处理转移到应用程序的外部服务中,您仍然可以通过将处理转移到另一种方法来推迟处理直到需要处理,这样创建控制器实例的成本不会太高。

      public class HomeController
      {
          public HomeController() {
          };
      
          private IProcessingResult DoSomethingExpensive() {
              // Lots of heavy processing
              System.Threading.Thread.Sleep(300);
          }
      
          public ActionResult Index()
          {
              var result = this.DoSomethingExpensive();
      
              // Do something with the result of the heavy processing
      
              return View();
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-05-22
        • 1970-01-01
        • 2015-04-02
        • 2015-08-28
        • 2017-12-12
        • 2015-06-14
        • 2013-05-14
        相关资源
        最近更新 更多