NOTE: For Umbraco v10/v13, use the Discipline package:
https://marketplace.umbraco.com/package/dotsee.discipline
which provides the functionality of the AutoNode, NodeRestrict, VirtualNodes, and VariantsHider packages together.
This package lets you specify one or more document types that will be excluded from Umbraco-generated URLs, thus making them "invisible". Those can be used as grouping nodes and they will not appear as part of the URL.
Usage
After you install the package, you will have to add one appSettings entry to your web.config file, as follows:
<add key="virtualnode" value="docTypeToMakeVirtual"/>
Where docTypeToMakeVirtual is the document type alias you want to be treated as a "virtual" node.
You can define more than one "rules" for docTypes by separating them with commas, as follows:
<add key="virtualnode" value="docTypeToMakeVirtual,anotherDocType"/>
You can also use wildcards at the start and/or the end of the document type alias, like this:
<add key="virtualnode" value="dog*,*cat,*mouse*"/>
This means that all document type aliases ending with "dog", all document types starting with "cat" and all those containing "mouse" will be treated as virtual nodes.
Advanced: Auto numbering of nodes
Consider the following example:
articles
groupingNode1
article1
article2
groupingNode2
Supposing that groupingNode1 and groupingNode2 are virtual nodes, the path for article1 will be /articles/article1. Okay, but what if we add a new article named "article1" under groupingNode2?
The plugin checks nodes on save and changes their names accordingly to protect you from this. More specifically, it checks if the parent node of the node being saved is a virtual node and, if so, it checks all its sibling nodes to see if there is already another node using the same name. It then adjusts numbering accordingly.
So, if you saved a new node named "article1" under "groupingNode2" it would become:
articles
groupingNode1
article1
article2
groupingNode2
article1 (1)
And then if you saved another node named "article1" again under "groupingNode1" it would become "article1 (2)" like this:
articles
groupingNode1
article1
article2
article1 (2)
groupingNode2
article1 (1)
This ensures that there are no duplicate urls. Of course, to keep things simple, I've implemented checks only a level up - if you have multiple virtual nodes under each other and multiple nodes with the same name in different levels, better be careful because no checks there. (Yes, I'm lazy).
Version History
1.0
Initial release
1.0.1
Bugfix: Content Finder would return a Dynamic node instead of IPublishedContent when getting a node's path from cache which would cause an exception when accessing the node for a second time.
Bugfix: Publishing a home page in case there were more than one homepages (e.g. multiple language) would cause an exception due to incorrect handling of levels.
1.0.2
Bugfix: Process normally when calling .UrlWithDomain() extension by removing the host part, processing paths and appending again at the end
1.0.3
Bugfix: Prevent exception when parent node is null (maybe unpublished or otherwise not yet persisted)
1.0.4
Bugfix: Prevent errors when node name is in the form "(my node name)" (quotes included)
Bugfix: The original node's name would change to a numbered one when more nodes with the same name had been added under the same virtual path and the original node was republished
1.1.0
Support for Umbraco 8.2+
Other Notes
This package will work with Umbraco version 7.5 or higher (tested on 7.5.2) which includes the new 301 redirect tracker. However, Umbraco cannot correctly track and create 301 redirects to urls that come from this package, so if the url for a node included in a path that contains one or more virtual nodes is renamed, the automatic 301 redirect created will be from the full (actual) path to the new (shortened path) and not from the full (shortened) path to the new (shortened) path.
That is, if the url /aaa/bbb/ccc is setup to create a virtual node (let's say for the doctype of "bbb") and becomes "/aaa/ccc" then renaming "ccc" to "ccc2" will create a 301 redirect rule as follows:
/aaa/bbb/ccc to /aaa/ccc2
instead of
/aaa/ccc to /aaa/ccc2
resulting in a 404 when trying to access /aaa/ccc (the old url with the hidden segment)
This only affects automatic 301 redirects, but otherwise the package is going to function correctly.
Related forum posting: https://our.umbraco.org/forum/extending-umbraco-and-using-the-api//79521-301-redirect-handler-and-omitting-url-segments-from-path