Running a default controller on content with no template
I have a weird scenario for which I would like to execute the same controller for every single inbound request and never invoke the standard Umbraco templating system.
I have found DefaultRenderMvcControllerResolver and assigned my default controller, which is good.
However, if a piece of content doesn't have a template assigned, it throws an error before getting to the Index action of the controller is hit (meaning, it never gets to the controller...)
No template exists to render the document at url '/whatever/'.
Umbraco must identify the content being addressed, retrieve it, then check for the assignment of a template, then not hand it to my controller if it has no template.
This means I need to make an empty template for every Document Type. I can do this, but it seems kind of wasteful.
How can I tell Umbraco "None of the content will have templates. Just run my controller anyway..."?
When using the CurrentTemplate helper in a RenderMvcController, a check is made for the existence of the view:
protected ActionResult CurrentTemplate<T>(T model)
{
var template = ControllerContext.RouteData.Values["action"].ToString();
if (EnsurePhsyicalViewExists(template) == false)
throw new Exception("No physical template file was found for template " + template);
return View(template, model);
}
which I thought was the error you were seeing
if so you could just work around this by having your own helper for returning the Current Template without the physical view check... or just directly in your CustomRenderMvcController like so:
public class CustomRenderMvcController : RenderMvcController
{
public override ActionResult Index(RenderModel model)
{
var template = ControllerContext.RouteData.Values["action"].ToString();
return View(template, model);
}
}
but actually I've spun up a copy of 7.12.4 to test this, and you are right, the index doesn't get hit, at the point where Umbraco assembles the PublishedContentRequest item associated with the request, it checks for a template... and regardless if it's hijacked, returns the not found handler, that displays the message you see.
There is a published content prepared event, that we can handle before this check, but it appears the HasTemplate is read only, otherwise we could just set it to true to avoid this,
You must have edited your reply, because I tried the first version of your post, and came back here to note that it wasn't quite what I was looking for -- then I saw the expanded version. :-)
There are two checks, it seems:
That a template is assigned to the content
That a physical file for that template exists
I'm failing on that first check. I've actually deleted the underlying file, and it doesn't seem to matter, because the execution never gets to the point where it even looks for the physical file. It gets uptight when it finds that nothing is assigned.
Not a big deal -- I'll just create a "Null Template" and assign it to everything.
Yes I sort of answered first without thinking, and then thought, hmm, he's not actually hitting his controller index action at all, hmm, and thought I'd try it out...
Anyway I think you can work around it without having to set the templates explicitly in the backoffice for ALL the document types.
if you have one empty template in the BackOffice, then you can use the PublishedContentRequest_Prepared event to set that template in code for all your requests. eg:
When I publish the site from dev out of VS, it's over-writing the umbraco.config file in App_Data. My dev instance has different content, so the umbraco.config running in production no longer matches what's in the database.
I deleted that file, then republished the entire site, and all is good now.
But, follow-on question: should I not publish App_Data? I've found there are files in here that need to be published -- I have paths in web.config to files in NuGetBackup, for instance.
What am I doing wrong here? Do exclude App_Data or not?
Running a default controller on content with no template
I have a weird scenario for which I would like to execute the same controller for every single inbound request and never invoke the standard Umbraco templating system.
I have found
DefaultRenderMvcControllerResolver
and assigned my default controller, which is good.However, if a piece of content doesn't have a template assigned, it throws an error before getting to the
Index
action of the controller is hit (meaning, it never gets to the controller...)Umbraco must identify the content being addressed, retrieve it, then check for the assignment of a template, then not hand it to my controller if it has no template.
This means I need to make an empty template for every Document Type. I can do this, but it seems kind of wasteful.
How can I tell Umbraco "None of the content will have templates. Just run my controller anyway..."?
If this is for EVERY inbound request, then a HTTP Module might be a more efficient approach.
I should have worded this better.
I want to run code for every successful request to a known content object.
Specifically, I want...
Sorry. I was unclear.
Hi Deane
When using the CurrentTemplate helper in a RenderMvcController, a check is made for the existence of the view:
which I thought was the error you were seeing
if so you could just work around this by having your own helper for returning the Current Template without the physical view check... or just directly in your CustomRenderMvcController like so:
but actually I've spun up a copy of 7.12.4 to test this, and you are right, the index doesn't get hit, at the point where Umbraco assembles the PublishedContentRequest item associated with the request, it checks for a template... and regardless if it's hijacked, returns the not found handler, that displays the message you see.
https://github.com/umbraco/Umbraco-CMS/blob/dd6e764588d22ef2b7bce01fd504ece89834f181/src/Umbraco.Web/Routing/PublishedContentNotFoundHandler.cs
I think it is meant to work though; looking at this comment here:
https://github.com/umbraco/Umbraco-CMS/blob/dd6e764588d22ef2b7bce01fd504ece89834f181/src/Umbraco.Web/Mvc/RenderRouteHandler.cs#L295
There is a published content prepared event, that we can handle before this check, but it appears the HasTemplate is read only, otherwise we could just set it to true to avoid this,
https://github.com/umbraco/Umbraco-CMS/blob/dd6e764588d22ef2b7bce01fd504ece89834f181/src/Umbraco.Web/Routing/PublishedContentRequest.cs
hmm, sorry, interesting, but not very helpful reply!
regards
Marc
You must have edited your reply, because I tried the first version of your post, and came back here to note that it wasn't quite what I was looking for -- then I saw the expanded version. :-)
There are two checks, it seems:
I'm failing on that first check. I've actually deleted the underlying file, and it doesn't seem to matter, because the execution never gets to the point where it even looks for the physical file. It gets uptight when it finds that nothing is assigned.
Not a big deal -- I'll just create a "Null Template" and assign it to everything.
Hi Deane
Yes I sort of answered first without thinking, and then thought, hmm, he's not actually hitting his controller index action at all, hmm, and thought I'd try it out...
Anyway I think you can work around it without having to set the templates explicitly in the backoffice for ALL the document types.
if you have one empty template in the BackOffice, then you can use the PublishedContentRequest_Prepared event to set that template in code for all your requests. eg:
That enables me to hit the Index Action of the the custom Default RenderMvcController, when the document has no template assigned...
regards
Marc
This worked beautifully. Thank you.
I did find another issue: if there's no template assigned, Umbraco doesn't generate a URL for it. Under the "Info" tab, you get:
Hi Deane
It should generate the URL anyway, try saving and publishing again to purge the cache.
I see what happened.
When I publish the site from dev out of VS, it's over-writing the
umbraco.config
file inApp_Data
. My dev instance has different content, so theumbraco.config
running in production no longer matches what's in the database.I deleted that file, then republished the entire site, and all is good now.
But, follow-on question: should I not publish
App_Data
? I've found there are files in here that need to be published -- I have paths in web.config to files inNuGetBackup
, for instance.What am I doing wrong here? Do exclude
App_Data
or not?is working on a reply...