Update 2/17/2015 . Adobe has confirmed my suspicions on its own blog, http://blogs.coldfusion.com/post.cfm/onmissingtemplate
I faced the same situation using ColdFusion 9 and IIS 7.5. I was waiting for an answer in the hope that someone else would share their configuration, and also because I'm not too happy with the “resolution” that I came up with. I will swallow my pride and publish what I have done for this situation. Feel free to comment.
My conclusions first. It's been a while since I worked on this, but here's what I remember. In the ColdFusion administrator, in the "Server Settings - Settings" section, if you select the "Enable HTTP status codes" checkbox, which causes this situation. This parameter causes the ColdFusion server to return status codes, such as 404 (and others) with it. Therefore, when IIS receives this 404 status after processing ColdFusion, it also processes the 404 error handler. If the Enable HTTP status codes check box is not selected, ColdFusion will send 200 OK for ALL errors (including 500 errors). When IIS receives status 200, it assumes that everything is in order and does not process error handlers. This may be what some people want; when ColdFusion handles its own errors and the IIS that it owns - separately. Do not return the actual status code 404, however, this could be detrimental to search engine indexing.
Like you, this is not what I wanted. I wanted IIS and ColdFusion to share the same 404 handler. Unlike you, I wanted all 404 errors to be handled by ColdFusion, not a static HTML page. This allows me to do a few things. When pages are moved or renamed, I can handle the ColdFusion 404 handler and redirect the request accordingly. Even changing the status code, which is useful for indexing search engines (301 and / or 302 code). I can also create short abbreviations if I want to avoid this, error logs, email errors, etc.
So, in my configuration, I have IIS 404 errors pointing to my ColdFusion page. In the ColdFusion admin, I have a skipped template handler pointing to the same ColdFusion page, and I have the option "Enable HTTP status codes" enabled (checked). With this setting, page 404 is called twice for all non-existent .cfm templates (both from IIS and CF handlers), but it is called only once for every other file type (only from IIS).
I never found a way to avoid duplicate 404 processing for nonexistent .cfm templates, so I added code to my ColdFusion page. (Note that I can do this because the 404 handler is a ColdFusion page, not a static HTML page.) I just need a way to differentiate when the page was called from the IIS handler and the ColdFusion handler. I found that whenever an IIS 404 handler calls a ColdFusion page, the variable CGI.SCRIPT_NAME
is the file name of my ColdFusion page, regardless of which page is actually being requested. (IIS adds the requested URL to the query string added with 404;) When the ColdFusion missing handler handler invokes the page, the CGI.SCRIPT_NAME
variable contains the actual file name of the requested ColdFusion template.
Example URL from IIS 404 Handler:
http://www.yourdomain.com/404handler.cfm?404;http://www.yourdomain.com:80/non-existent-file.cfm
Example ColdFusion URL form missing template handler:
http:
Knowing this, I can now include some code in the ColdFusion handler to basically ignore one of the requests. I prefer to ignore the ColdFusion request because they are only for .cfm templates. IIS requests will be for all files. So, at the top of my ColdFusion 404 page, I have code like this (this is not very pretty, but it seems to work for me):
<cfif CGI.SCRIPT_NAME NEQ "/404handler.cfm"> <cfelse> </cfif>
Another thing I noticed with this. When a request comes through the ColdFusion handler, it does not match the life cycle of a regular request. I.E. The request does not call the Application.cfm file. Therefore, you need to be careful if you use application variables on the ColdFusion page that you set for the missing template handler. (You can always simply cfinclude
Application.cfm file for these requests.) When the request arrives through the IIS 404 handler, it processes the Application.cfm file as usual. I assume IIS is making a request for the .cfm file.
When using the Application.cfc onMissingTemplate function, the ColdFusion administrator parameter is completely eliminated in favor of the function. When this function is triggered, it also does not flow through the normal request life cycle. You should also check for application variables in this function (if you use any functions), as this has already bit me.