我已经为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毫秒才能加载页面。这里出了点问题。
为什么我的菜单修剪基于角色的想法很慢?我没有做任何自定义。
答案 0 :(得分:0)
答案 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();
}
}