I've turned on some logging for two requests, one straight to the content API which is successful. And one that fails, utilizing friendlyUrls.
Successful content API request:
INFO EPiServer.ContentApi.Core.InitializationService: Start initializing virtual role for Headless APi
DEBUG EPiServer.Shell.Web.Routing.ModuleRouteCollection: Not routing '~/api/episerver/v2.0/content/18949' since it doesn't start with '~/EPiServer/EPiServer.Labs.LanguageManager/3.2.0'
...
DEBUG EPiServer.Shell.Web.Routing.ModuleRouteCollection: Not routing '~/api/episerver/v2.0/content/18949' since it doesn't start with '~/modules'
DEBUG EPiServer.Web.TemplateResolver: CustomerServiceStartPage: Selected CustWeb.UI.Controllers.Pages.CustomerServiceStartPageController. (tag='', channel='web', category='Request')
DEBUG EPiServer.Web.TemplateResolver: StartPage: Selected CustWeb.UI.Controllers.Pages.StartPageController. (tag='', channel='web', category='Request')
DEBUG EPiServer.Web.TemplateResolver: CustomerServiceStartPage: Selected CustWeb.UI.Controllers.Pages.CustomerServiceStartPageController. (tag='', channel='web', category='Request')
DEBUG EPiServer.Web.TemplateResolver: ImageFile: Selected EPiServer.CdnSupport.CdnMediaHandler. (tag='', channel='web', category='Request')
DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: Begin: Get Current CustomRedirectHandler
DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: Returning cached handler.
DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: End: Get Current CustomRedirectHandler
DEBUG BVNetwork.NotFound.Core.RequestHandler: Not a 404 response.
Request URL: http://ENVIRONMENT/api/episerver/v2.0/content/18949
Response status code: 200
Erroneous friendlyUrl request (Accept header 'application/json'):
INFO EPiServer.ContentApi.Core.InitializationService: Start initializing virtual role for Headless APi
DEBUG EPiServer.Shell.Web.Routing.ModuleRouteCollection: Not routing '~/nks' since it doesn't start with '~/EPiServer/EPiServer.Labs.LanguageManager/3.2.0'
...
DEBUG EPiServer.Shell.Web.Routing.ModuleRouteCollection: Not routing '~/nks' since it doesn't start with '~/modules'
DEBUG EPiServer.Web.Routing.Segments.Internal.NodeSegment: Url 'http://ENVIRONMENT/nks' was routed to content with id '18949' and language was set to 'sv'
DEBUG EPiServer.Web.TemplateResolver: CustomerServiceStartPage: Selected CustWeb.UI.Controllers.Pages.CustomerServiceStartPageController. (tag='', channel='web', category='MvcController')
DEBUG EPiServer.Web.Routing.Segments.Internal.NodeSegment: Url 'http://ENVIRONMENT/api/episerver/v2.0/content/18949' was routed to content with id '1' and language was set to ''
DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: Begin: Get Current CustomRedirectHandler
DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: Returning cached handler.
DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: End: Get Current CustomRedirectHandler
DEBUG BVNetwork.NotFound.Core.RequestHandler: Handling 404 request.
Request URL: http://ENVIRONMENT/api/episerver/v2.0/content/18949
Response status code: 404
The line: DEBUG EPiServer.Web.Routing.Segments.Internal.NodeSegment: Url 'http://ENVIRONMENT/api/episerver/v2.0/content/18949' was routed to content with id '1' and language was set to ' ' seems really strange to me here.
Hi Michael,
1. Does your site have any custom routing ? ContentDeliveryAPi's custom routing and yours (or routing in other products e.g Commerce) may step on each other so causing conflict. This is just my guess.
2. ContentDeliveryAPi's friendly url feature may not work with SimpleAddress.
3. So, till now you're able to reproduce the error on your local machine with stand alone IIS Server ? We'd like to know the steps to reproduce the error so we can dig deeper.
Hello Michael and Quan
I would be really interested in a solution a well :). We have the same problem.
The Content API url works (direct postman call to: http://xxxx.localhost/api/episerver/v2.0/content/3683/children works).
The Search Content url works (direct postmand call to http://xxxx.localhost/api/episerver/v2.0/search/content/?filter=tolower(name) eq 'vuetest' works)
But the friendly url routing does seem to not work.
It does find the correct url redirect if you look at the log: http://xxxx.localhost/en/vuetest/children => http://xxxx.localhost/api/episerver/v2.0/content/3683/children
But it seems the accept-language header value is lost somehow or the ID gets lost because it ends up with 1?
Quan: What do you mean with 'SimpleAddress'?
Kind regards
Remco
Error:
2019-05-08 08:37:36,005 [29] DEBUG EPiServer.Shell.Web.Routing.ModuleRouteCollection: Not routing '~/en/vuetest/children' since it doesn't start with '~/modules'
2019-05-08 08:37:36,006 [29] DEBUG EPiServer.Web.Routing.Segments.Internal.NodeSegment: Url 'http://xxxx.localhost/en/vuetest/children' was routed to content with id '3683' and language was set to 'en'
2019-05-08 08:37:36,008 [29] DEBUG EPiServer.Web.TemplateResolver: FrontEndPage: Selected SpecialtyChemicals.Site.Controllers.Pages.FrontEndPageController. (tag='', channel='web', category='MvcController')
2019-05-08 08:37:36,009 [29] DEBUG EPiServer.Web.Routing.Segments.Internal.NodeSegment: Url 'http://xxxx.localhost/api/episerver/v2.0/content/3683/children' was routed to content with id '1' and language was set to 'en'
2019-05-08 08:37:36,010 [29] DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: Begin: Get Current CustomRedirectHandler
2019-05-08 08:37:36,011 [29] DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: Returning cached handler.
2019-05-08 08:37:36,012 [29] DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: End: Get Current CustomRedirectHandler
2019-05-08 08:37:36,012 [29] DEBUG BVNetwork.NotFound.Core.RequestHandler: Handling 404 request.
Request URL: http://xxxx.localhost/api/episerver/v2.0/content/3683/children
Response status code: 404
Hi Quan!
Just for brevity, I'll include the succsessful request log for IIS Express:
INFO EPiServer.ContentApi.Core.InitializationService: Start initializing virtual role for Headless APi
DEBUG EPiServer.Shell.Web.Routing.ModuleRouteCollection: Not routing '~/nks' since it doesn't start with '~/EPiServer/EPiServer.Labs.LanguageManager/3.2.0'
DEBUG EPiServer.Shell.Web.Routing.ModuleRouteCollection: Not routing '~/nks' since it doesn't start with '~/modules'
DEBUG EPiServer.Web.Routing.Segments.Internal.NodeSegment: Url 'https://ENVIRONMENT:44302/nks' was routed to content with id '18949' and language was set to 'sv'
DEBUG EPiServer.Web.TemplateResolver: CustomerServiceStartPage: Selected CustWeb.UI.Controllers.Pages.CustomerServiceStartPageController. (tag='', channel='web', category='MvcController')
DEBUG EPiServer.Web.Routing.Segments.Internal.NodeSegment: Url 'https://ENVIRONMENT:44302/api/episerver/v2.0/content/18949' was routed to content with id '1' and language was set to ''
INFO EPiServer.ContentApi.Core.InitializationService: Start initializing virtual role for Headless APi
DEBUG EPiServer.Shell.Web.Routing.ModuleRouteCollection: Not routing '~/api/episerver/v2.0/content/18949' since it doesn't start with '~/EPiServer/EPiServer.Labs.LanguageManager/3.2.0'
DEBUG EPiServer.Shell.Web.Routing.ModuleRouteCollection: Not routing '~/api/episerver/v2.0/content/18949' since it doesn't start with '~/modules'
DEBUG EPiServer.Web.TemplateResolver: CustomerServiceStartPage: Selected CustWeb.UI.Controllers.Pages.CustomerServiceStartPageController. (tag='', channel='web', category='Request')
DEBUG EPiServer.Web.TemplateResolver: StartPage: Selected CustWeb.UI.Controllers.Pages.StartPageController. (tag='', channel='web', category='Request')
DEBUG EPiServer.Web.TemplateResolver: CustomerServiceStartPage: Selected CustWeb.UI.Controllers.Pages.CustomerServiceStartPageController. (tag='', channel='web', category='Request')
DEBUG EPiServer.Web.TemplateResolver: ImageFile: Selected EPiServer.Web.Internal.ContentMediaHttpHandler. (tag='', channel='web', category='Request')
DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: Begin: Get Current CustomRedirectHandler
DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: Returning cached handler.
DEBUG BVNetwork.NotFound.Core.CustomRedirects.CustomRedirectHandler: End: Get Current CustomRedirectHandler
DEBUG BVNetwork.NotFound.Core.RequestHandler: Not a 404 response.
Request URL: https://ENVIRONMENT:44302/api/episerver/v2.0/content/18949
Response status code: 200
Hi Remco and Michael,
Thanks a lot for your information
1. I mean SimpleAress in EditMode. If we use SimpleAdress to get content's ancestors or children it may not work (this is the limitation of ContentDeliveryApi)
2. ContentApi's partial router may disrupt other routers in the site (or vice-versa).
This can disrupt other partial routers in the site because the request URL is rewritten. To solve this problem, follow these steps:
CustomContentApiRouteService
) that inherits ContentApiRouteService
and then, register a transient lifecycled implementation for a ContentApiRouteService in the initialization service.ShouldRouteRequest
to prevent the URL from being re-written in unexpected cases. For example, requests whose accept types contain application/json are currently handled by our partial router (accept type application/json is a common header). So, you can add one more header (for example, Routed-By-ContentApi) for CD-related requests and then, use this header in the function to decide whether our partial router should handle the request and rewrite URL later on. For example
using EPiServer.ContentApi.Routing;
using System.Web;
public class CustomContentApiRouteService : ContentApiRouteService
{
public override bool ShouldRouteRequest(HttpRequestBase request)
{
// By default, Requests which have accept headers 'application/json' will be routed.
//if (request != null && request.AcceptTypes?.Contains(RouteConstants.JsonContentType) == true)
//{
// return true;
//}
bool isRoutedByContentApi = false;
if (bool.TryParse(request.Headers["Route-By-ContentApi"], out isRoutedByContentApi))
{
return isRoutedByContentApi;
}
return false;
}
}
3. If you have configuration handlers in web.config like below, ContentApi friendly url will throw 404. The order of handlers should be reversed (or you can try removing StaticFileHandler)
We're sill trying to figure out the root cause.
If one of these approaches works for you, please let us know.
Thanks again!
Hi Quan
Thanks for the fast response.
Hi Quan,
Not working:
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</handlers>
Working:
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</handlers>
I don't have an explanation to why, but maby you have? At least it's working now :)
Nice Remco!
I don't know to why this is, but it feels strange that we had the preCondition classicMode since the site runs in integrated-mode. I'm fairly new in this project so don't know the history but maybe it's just legacy stuff in our web.config.
We've got an issue with the headless content api, in some cases.
Everything works fine while we're running local dev on IIS Express, both firendly-url (which our Angular app relies on) as well as /api/episerver/v2.0/content/XXXX requests works. However, after deploying to Azure, we get a 404 Not Found from the content api-request. Though making the same CURL request to https://AZURE/api/episerver/v2.0/content/XXXX does work. So it seems like the content-api works, but there's some configuration differences web server-wise.
We've managed to reproduce the error locally by setting up a stand alone IIS server for the site, but it's a bit hard to debug this issue. Does anyone have any suggestions what could be causing this?
We've followed setup and configuration:
https://world.episerver.com/documentation/developer-guides/content-delivery-api/configuration/
https://world.episerver.com/documentation/developer-guides/content-delivery-api/using-friendly-urls/