Sorry if I am spamming the forum, but I have another issue that is causing me a lot of pain.
When I use insomnia to query pages on my site, I get quite a fast response, as I would expect:
But take a look at this controller:
It doesn't do anything, query anything or create anything. It simply returns a response of OK to the client.
But check this out:
I don't understand why it takes about 30 times longer to return a response from a custom API than a page on the site?
Are there some middlewares that are doing things on these kinds of routes? If so is there a way I can turn them off or work around them?
I have removed all of my own middlewares for this test, so it is not that.
However, when I use it I get a MASSIVE degradation in performance.
I would like to keep my API routes following a nice REST pattern, but I cant do that If I need all my routes to follow the pattern:
~/Umbraco/Api/[YourControllerName]/[YourActionName]
Does anyone know a way around the issue described above?
In summary, create an umbraco controller with a simple OK response and watch the timings when you hit it in a REST client. Then add a route attribute and hit it again.
Locally here I am seeing the response times go from single digit milliseconds to hundreds of miliseconds.
Just an observation, in your first code example you are inheriting from ControllerBase, in the second you are inheriting from UmbracoApiController. If you put the routing attribute on the second controller do you get the same slower response?
Thanks for your response.
Yes, unfortunately it is the attribute the causes the change in response time. The slower response time happens when you inherit from either controller, when you use the attribute.
It seems to me that it is something like Umbraco performing all of its routing logic before the attributes are processed... but I have never looked at the source code for routing.
Are you running in Debug or Release mode?
.NET normally doesn't enable route caching when running in Debug so there can be a massive performance difference between the two.
After multiple. It starts longer, like 800ms, then goes down to about 200 to 250. I think I have found something though.
I just turned on verbose logging in both scenarios.
When there is no custom attribute, I see this in the logs:
[10:42:28 VRB] Begin request [6daa40fc-f433-4238-a725-367e695d49a1]: /umbraco/api/articles/getarticles
[10:42:28 VRB] End Request [6daa40fc-f433-4238-a725-367e695d49a1]: /umbraco/api/articles/getarticles (0.9288ms)
But when I have a custom attribute, i see this:
[10:37:14 VRB] Begin request [014d3d38-cf00-4b52-9aae-541194e611da]: /api/articles
[10:37:14 VRB] Create 54fdff88 on thread 9
[10:37:14 DBG] FindDomain: Uri=https://localhost:44376/api/articles
[10:37:14 DBG] FindDomain: Matches no domain
[10:37:14 DBG] FindDomain: Culture=en-US
[10:37:14 DBG] FindPublishedContentAndTemplate: Path=/api/articles
[10:37:14 DBG] FindPublishedContent: Begin finders [Timing d257252]
[10:37:14 DBG] Finder Umbraco.Cms.Core.Routing.ContentFinderByPageIdQuery
[10:37:14 DBG] Finder Umbraco.Cms.Core.Routing.ContentFinderByUrl
[10:37:14 DBG] Test route /api/articles
[10:37:14 DBG] No match.
[10:37:14 DBG] Finder Umbraco.Cms.Core.Routing.ContentFinderByIdPath
[10:37:14 DBG] Not a node id
[10:37:14 DBG] Finder Umbraco.Cms.Core.Routing.ContentFinderByUrlAlias
[10:37:14 DBG] Finder Umbraco.Cms.Core.Routing.ContentFinderByRedirectUrl
[10:37:14 VRB] Create 5edc383e on thread 9
[10:37:14 DBG] No match for route: /api/articles
[10:37:14 DBG] Found? False, Content: NULL, Template: NULL, Domain: NULL, Culture: en-US, StatusCode: null
[10:37:14 DBG] FindPublishedContent: End finders (268ms) [Timing d257252]
[10:37:14 DBG] HandlePublishedContent: Loop 0
[10:37:14 DBG] HandlePublishedContent: No document, try last chance lookup
[10:37:14 DBG] Looking for a page to handle 404.
[10:37:14 DBG] Got nothing.
[10:37:14 DBG] HandlePublishedContent: Failed to find a document, give up
[10:37:14 DBG] HandlePublishedContent: End
[10:37:14 DBG] RewriteForPublishedContentAccessAsync: Loop 0
[10:37:14 VRB] End Request [014d3d38-cf00-4b52-9aae-541194e611da]: /api/articles (269.3097ms)
It looks like when it doesnt match an umbracoapi route, it goes and tries to find a matching content item before it does the attribute routing.
This seems incorrect to me. I'd imagine if I have deliberately put a custom routing attribute on a controller, I would like that to be evaluated first.
Just wanted to say thank you and confirm that this issue is present in V10 as well. When ReservedPaths is not set all IContentFinder's will be triggered (and probably other stuff) hence the extra time for the response.
API Controller slower than regular pages
Hi All,
Sorry if I am spamming the forum, but I have another issue that is causing me a lot of pain.
When I use insomnia to query pages on my site, I get quite a fast response, as I would expect:
But take a look at this controller:
It doesn't do anything, query anything or create anything. It simply returns a response of OK to the client.
But check this out:
I don't understand why it takes about 30 times longer to return a response from a custom API than a page on the site?
Are there some middlewares that are doing things on these kinds of routes? If so is there a way I can turn them off or work around them? I have removed all of my own middlewares for this test, so it is not that.
Many thanks
Ah.... ok wait.
It if I take away the "Route" attribute and use "UmbracoApiController" instead:
I get much better performance:
:)
Sorry for the spam. But instead of deleting the question, I'll leave it here in case anyone else has the same issue.
I have actually changed my mind on this.
My solution above is not a solution. The documentation here states that you can use attribute routing:
https://our.umbraco.com/documentation/reference/routing/webapi/#using-mvc-attribute-routing-in-umbraco-web-api-controllers
However, when I use it I get a MASSIVE degradation in performance.
I would like to keep my API routes following a nice REST pattern, but I cant do that If I need all my routes to follow the pattern: ~/Umbraco/Api/[YourControllerName]/[YourActionName]
Does anyone know a way around the issue described above?
In summary, create an umbraco controller with a simple OK response and watch the timings when you hit it in a REST client. Then add a route attribute and hit it again.
Locally here I am seeing the response times go from single digit milliseconds to hundreds of miliseconds.
Any suggestions would be greatly appreciated.
Hi Keith,
Just an observation, in your first code example you are inheriting from
ControllerBase
, in the second you are inheriting fromUmbracoApiController
. If you put the routing attribute on the second controller do you get the same slower response?Thanks
Nik
Hi Nik,
Thanks for your response. Yes, unfortunately it is the attribute the causes the change in response time. The slower response time happens when you inherit from either controller, when you use the attribute.
It seems to me that it is something like Umbraco performing all of its routing logic before the attributes are processed... but I have never looked at the source code for routing.
Are you running in Debug or Release mode? .NET normally doesn't enable route caching when running in Debug so there can be a massive performance difference between the two.
Thanks Thomas,
Ill try that suggestion and see if it helps!
No dice, unfortunately:
With custom route attribute
Without custom route attribute
The controller:
Is that first request or after multiple?
After multiple. It starts longer, like 800ms, then goes down to about 200 to 250. I think I have found something though.
I just turned on verbose logging in both scenarios.
When there is no custom attribute, I see this in the logs:
But when I have a custom attribute, i see this:
It looks like when it doesnt match an umbracoapi route, it goes and tries to find a matching content item before it does the attribute routing.
This seems incorrect to me. I'd imagine if I have deliberately put a custom routing attribute on a controller, I would like that to be evaluated first.
Try to exclude the endpoint via configuration: https://our.umbraco.com/documentation/Reference/V9-Config/GlobalSettings/
see: ReservedPaths
you could add: "~/api/" to enclude all endpoints below /api/ from umbraco's routing Like this:
That's amazing thanks!
Adding the path to the reserved routes gives me decent performance now!
Hi Guys!
Just wanted to say thank you and confirm that this issue is present in V10 as well. When
ReservedPaths
is not set allIContentFinder
's will be triggered (and probably other stuff) hence the extra time for the response.In V10 (and probably 9) it looks like this:
is working on a reply...