It is not currently possible to add "static" nodes to dynamic nodes when using MvcSiteMapNodeAttribute. However, you can add "static" nodes (that is, children of data-driven nodes) directly within your IDynamicNodeProvider implementation.
public class PeopleDynamicNodeProvider
: DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
using (var db = new MyContext())
{
// Create a node for each album
foreach (var person in db.People)
{
string personKey = "Person_" + person.Id.ToString();
DynamicNode dynamicNode = new DynamicNode();
dynamicNode.Key = personKey;
dynamicNode.Title = person.Name;
dynamicNode.ParentKey = "People"; // Attach to a node that is defined somewhere else
dynamicNode.RouteValues.Add("id", person.Id.ToString());
yield return dynamicNode;
DynamicNode staticNode = new DynamicNode();
staticNode.Title = person.Name + " Details";
staticNode.ParentKey = personKey;
staticNode.Controller = "People";
staticNode.Action = "Details";
staticNode.RouteValues.Add("id", person.Id.ToString());
yield return staticNode;
}
}
}
}
If you really must define them using MvcSiteMapNodeAttribute, you can divide the above into 2 separate dynamic node providers, and then declare the second one on an attribute.
This will be quite a bit slower because of the additional overhead of multiple calls to the database. You could potentially fix that by request caching your people data so it is shared between providers.
public class PeopleDynamicNodeProvider
: DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
using (var db = new MyContext())
{
// Create a node for each album
foreach (var person in db.People)
{
string personKey = "Person_" + person.Id.ToString();
DynamicNode dynamicNode = new DynamicNode();
dynamicNode.Key = personKey;
dynamicNode.Title = person.Name;
dynamicNode.ParentKey = "People"; // Attach to a node that is defined somewhere else
dynamicNode.RouteValues.Add("id", person.Id.ToString());
yield return dynamicNode;
}
}
}
}
public class PeopleDetailsDynamicNodeProvider
: DynamicNodeProviderBase
{
public override IEnumerable<DynamicNode> GetDynamicNodeCollection(ISiteMapNode node)
{
using (var db = new MyContext())
{
// Create a node for each album
foreach (var person in db.People.Where(x => x.PersonCategoryId == node.Key))
{
string personKey = "Person_" + person.Id.ToString();
DynamicNode staticNode = new DynamicNode();
staticNode.Title = person.Name + " Details";
staticNode.Key = person.PersonCategoryId;
staticNode.ParentKey = personKey;
staticNode.Controller = "People";
staticNode.Action = "Details";
staticNode.RouteValues.Add("id", person.Id.ToString());
yield return staticNode;
}
}
}
}
And your attribute definition would then look something like this:
[MvcSiteMapNode(Title = "Placeholder Title (won't be seen)", Key = "Accidents", PreservedRouteParameters = "personId", DynamicNodeProvider = "MyNamespace.PeopleDetailsDynamicNodeProvider, MyAssembly")]
There is no constraint in a Dynamic Node provider that the number of nodes you produce has to exactly match the number of records in the database - you can create more nodes if you need to depending on your requirements.
Note: You may need to adjust the key/parent key mapping depending on how your data is actually organized.