第一次调用Url.Action在页面上的速度很慢 [英] First call to Url.Action on a page is slow
问题描述
我在使用相当简单的ASP.MVC视图时遇到性能问题.
I have a performance issue with a fairly simple ASP.MVC view.
这是一个登录页面,应该几乎是即时的,但是大约需要半秒钟.
It's a log-on page that should be almost instant, but is taking about half a second.
经过大量挖掘,似乎是第一个调用Url.Action
的问题-大约需要450毫秒(根据 MiniProfiler ),但似乎太慢了.
After a lot of digging it looks like the problem is the first call the Url.Action
- it's taking around 450ms (according to MiniProfiler) but that seems insanely slow.
随后对Url.Action
的调用花费的时间少于1ms,这与我的预期更加一致.
Subsequent calls to Url.Action
are taking <1ms, which is more in line with what I would expect.
无论我使用Url.Action("action", "controller")
还是Url.Action("action")
,这都是一致的,但是如果使用Url.Content("~/controller/action")
,这似乎不会发生.当我呼叫Html.BeginForm("action")
时也会发生这种情况.
This is consistent whether I use Url.Action("action", "controller")
or Url.Action("action")
, but doesn't seem to happen if I use Url.Content("~/controller/action")
. This also happens when I call Html.BeginForm("action")
.
有人知道这是什么原因吗?
Does anyone have any idea what's causing this?
深入研究源提示RouteCollection.GetVirtualPath
可能是罪魁祸首,因为这对于Url.Action
和Html.BeginForm
都是常见的.但是,肯定在整个地方都使用过吗?我的意思是½秒太慢了.
A dig into the source suggests that RouteCollection.GetVirtualPath
might be the culprit, as that's common to both Url.Action
and Html.BeginForm
. However, surely that's used all over the place? I mean, ½ a second is far too slow.
我有20条左右的自定义路由(这是一个带有一些旧版WebForms页面的相当大的应用程序),但即使那样,时间似乎也太慢了.
I have 20 or so custom routes (it's a fairly large app with some legacy WebForms pages) but even then the times seem far too slow.
有什么解决办法吗?
推荐答案
发现问题,并且与路由表有关(欢呼基里尔).
Problem found, and it is with the routing tables (cheers Kirill).
基本上,我们有很多路线看起来像这样:
Basically we have lots of routes that look something like this:
string[] controllers = GetListOfValidControllers();
routes.MapRoute(
name: GetRouteName(),
url: subfolder + "/{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional },
constraints: new { controller = "(" + string.Join("|", controllers) + ")" });
事实证明,正则表达式检查非常慢,痛苦的缓慢.因此,我将其替换为IRouteConstraint
的实现,该实现只是针对HashSet
进行了检查.
It turns out that the Regex check is very slow, painfully slow. So I replaced it with an implementation of IRouteConstraint
that just checks against a HashSet
instead.
然后我更改了地图路线调用:
Then I changed the map route call:
routes.MapRoute(
name: GetRouteName(),
url: subfolder + "/{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional },
constraints: new { controller = new HashSetConstraint(controllers) });
我还将链接文章中提到的 RegexConstraint 用于更复杂的事情-包括许多这样的调用(因为我们有旧版WebForm页面):
I also used the RegexConstraint mentioned in that linked article for anything more complicated - including lots of calls like this (because we have legacy WebForm pages):
routes.IgnoreRoute(
url: "{*allaspx}",
constraints: new { allaspx = new RegexConstraint( @".*\.as[pmh]x(/.*)?") });
这两个简单的更改可以完全解决问题;现在Url.Action
和Html.BeginForm
花费的时间可以忽略不计(即使有很多路线).
Those two simple changes completely fix the problem; Url.Action
and Html.BeginForm
now take a negligible amount of time (even with lots of routes).
这篇关于第一次调用Url.Action在页面上的速度很慢的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!