I feel like there is a better / easier way of doing this but I couldn’t find a resource online that works (and there isn’t much I could find at the time of writing). So I’m sharing this post as an option that works, incase you haven’t found a better solution. For those who have better solutions, please share! 🙂
Note: This post assumes you already have a 404 error page set up and that you’re using Geta’s 404 Handler
The problem with a web.config that has a 404 path without any language context
I’ve tried adding the prefixLanguageFilePath
to the <error ..> tag in the httpErrors
but that did not work. This is what it looks like:
<httpErrors errorMode="Custom" existingResponse="Replace">
<remove statusCode="404" />
<error statusCode="404" path="/404" responseMode="ExecuteURL" />
</httpErrors>
As you can see, all 404 requests are served with a response from the URL “/404/, which means even if I attempted to navigate to say a “Polish” page with the URL “abc.com/pl/some-error-page”, it will always serve the response from the URL “abc.com/404/”, instead of “abc.com/pl/404/”.
Add logic to determine the language before serving the site-configured Error page path
Instead of blindly returning the requested 404 page, I had to check the original 404 URL and determine if there is a language path in the URL. So I added this private method in my ErrorPageController.Index() action:
public class ErrorPageController : PageControllerBase<ErrorPage>
{
[BVNetwork.NotFound.Core.NotFoundPage.NotFoundPage]
public ActionResult Index(ErrorPage currentPage)
{
currentPage = GetLocalisedOrDefaultErrorPage(currentPage);
var model = new PageViewModel<ErrorPage>(currentPage);
if (!PageEditing.PageIsInEditMode)
{
Response.Clear();
Response.StatusCode = currentPage.ErrorCode;
Response.TrySkipIisCustomErrors = true;
}
return View(model);
}
}
Here’s my implementation of the GetLocalisedOrDefaultErrorPage() method:
private ErrorPage GetLocalisedOrDefaultErrorPage(ErrorPage errorPage)
{
// Determine language of the NotFoundUrl
if (!string.IsNullOrEmpty(ViewBag.NotFoundUrl))
{
var uri = new Uri(ViewBag.NotFoundUrl);
// if URI segments of the NotFoundUrl are composed of: 1) "/", 2) "{lang}/" (i.e. "/pl/incorrecturl")
// then load the correct language of the Error page
if (uri.Segments.Length > 2 && uri.Segments[0] == "/" && uri.Segments[1].EndsWith("/"))
{
var firstWordSegmentInUrl = uri.Segments[1].Substring(0, uri.Segments[1].Length - 1);
// iterate over the existing languages for the error page
// and check if any of the languages' URL segment matches the first segment of the accessed URL
foreach (var language in errorPage.ExistingLanguages)
{
string languageSegment = "";
if (!_languageSegmentMatcher.TryGetLanguageUrlSegment(language.Name, out languageSegment))
{
languageSegment = language.Name;
}
if (languageSegment == firstWordSegmentInUrl)
{
var errorPageInLanguage = _contentLoader.Get(errorPage.ContentLink, language);
if (errorPageInLanguage != null)
{
errorPage = errorPageInLanguage;
_updateCurrentLanguage.UpdateLanguage(language.Name);
}
}
}
}
}
return errorPage;
}
It’s time to test your 404 pages
If you try to navigate to the URL’s with a language path, it should now try to locate whether you have an Error page for that specific language. Otherwise, it’ll try to serve the default custom Error path.
- abc.com/pl/some-error should return a Polish page
- abc.com/some/error should return the default error page (i.e. English)
I’m interested to see other (better) solutions, so please share if you know of one!