Workaround: fixing Umbraco template not found error

How to fix Umbraco Template not found custom 404 error?

In this post, I am gonna share a quick workaround on how you can resolve the Umbraco CMS Template not found error for published content.

Recently I had a strange issue while trying to render a view for document type (product).

For some reason, the Umbraco engine could not find a template for published content.

After entering the product URL address, a well-known error popped up: 

No template exists to render the document at URL ‘/en/products/coca-cola-0-33l-cherry’.

In addition, no template exists to render the custom 404.

This page can be replaced with a custom 404. Check the documentation for “custom 404”.

This page is intentionally left ugly 😉

Umbraco Template Not Exists Template Not Found Error

It is worth providing more details here to better understand the issue:

  • The product document type was created initially without a template
  • All products were published
  • Then, the template was created and assigned to the document type
  • All products were re-published (with a template assigned)
  • What’s funny, when reviewing published product nodes in Umbraco back office – each product had a template assigned
  • Moreover, in the document overview – the hostnames/routing were set correctly 

As I wrote before – the product template was assigned to the document type after the full list of products was published initially.

Maybe something went wrong there.

For some reason, I could not get the template working, even though the back office settings were good.

Let’s move to the best part – workaround 🙈.

Workaround – we all love hacks ;]

After a short brainstorming, I decided to create an additional ContentFinder which I named “MissingTemplateContentFinder”.

A brief description of the ContentFinder logic:

  • Find content based on request absolute path
  • Check the model type alias, when published content was found, 
  • If we found a product, try to set the template with “product” alias (the product view was Product.cshtml)
  • Return result of the operation (boolean)
public class MissingTemplateContentFinder : IContentFinder
{
   public bool TryFindContent(PublishedRequest request)
   {
      var content = request.UmbracoContext.Content.GetByRoute(request.Uri.AbsolutePath);

      if (content == null) return false;

      if (content.ContentType.Alias == Product.ModelTypeAlias)
      {
         request.PublishedContent = content;

         var result = request.TrySetTemplate("Product");

         return result;
      }

      return false;
   }
}

Note that, when you’re having a multilanguage site – you can have issues getting content by the route.

You should follow the great discussion here:

https://github.com/umbraco/Umbraco-CMS/issues/3850

To make it fully work – I had to modify the request’s absolute path a bit.

In my case removing the language from the URL helped, so the final route should be:

‘/produkte/coca-cola-0-33l-cherry’ instead of ‘/de/produkte/coca-cola-0-33l-cherry’.

You may also need this trick, so the updated code can look as follows:

public bool TryFindContent(PublishedRequest request)
{
   var content = request.UmbracoContext.Content.GetByRoute(FixRoutePath(request.Uri.AbsolutePath));

   if (content == null) return false;

   if (content.ContentType.Alias == Product.ModelTypeAlias)
   {
      request.PublishedContent = content;

      var result = request.TrySetTemplate("Product");

      return result;
   }

   return false;
}

/// <summary>
/// Fix language issue for route https://github.com/umbraco/Umbraco-CMS/issues/3850 
/// </summary>
/// <param name="absolutePath"></param>
/// <returns></returns>
private string FixRoutePath(string absolutePath)
{
   //Include your languages
   if (absolutePath.StartsWith("/en/") || absolutePath.StartsWith("/de/") || absolutePath.StartsWith("/ru/"))
   {
      return absolutePath.Remove(0, 3);
   }

   return absolutePath;
}

Once the content finder is ready – register MissingTemplateContentFinder into ContentFinders pipeline: 

composition.ContentFinders().InsertBefore<ContentFinderByUrl, MissingTemplateContentFinder>();

Final thoughts

The above workaround did a trick for me and I was able to fix the rendering for the document type. I have to mention I am not fully happy with this solution ;]

Did you have such a problem? How did you solve it?

Let me know in the comment below ⬇️.

Similar Posts