Question

I just got a 'problem' using the current MvcSiteMapProvider MVC5 (from nuget, upgraded from MVC4). I used to add a routevalue "title" to the RouteValues of DynamicNodes when creating them in my DynamicNodeProvider. This worked fine in the previous version, however no I get an error when attempting this:

An exception of type 'MvcSiteMapProvider.Collections.Specialized.ReservedKeyException' occurred in MvcSiteMapProvider.dll but was not handled in user code

Additional information: The node with key 'someKey' may not add a route value with the key 'title' and value 'someValue' to the RouteValues dictionary because the key is a reserved name. Reserved names are keys that are meant for use internally by MvcSiteMapProvider rather than a dictionary value.

I get the message, I am not supposed to add the "title" as a custom route parameter. However, my complete project uses "{title}" in the route definitions, and I would have to change everything from title to "{id}" (or something else).

Now my question: is it somehow possible to add the custom "title" routevalue to the dynamicnodes anyway? Or is it simply not possible?

Thanks in advance!

Was it helpful?

Solution

You can get around this limitation by inheriting ReservedAttributeNameProvider and overriding the IsRouteAttribute method as follows.

public class MyReservedAttributeNameProvider
    : ReservedAttributeNameProvider
{
    public MyReservedAttributeNameProvider(
        IEnumerable<string> attributesToIgnore
        ) : base(attributesToIgnore)
    {
    }

    public override bool IsRouteAttribute(string attributeName)
    {
        return attributeName != "visibility"
            && !attributesToIgnore.Contains(attributeName)
            && !attributeName.StartsWith("data-");
    }
}

You can then inject your new ReservedAttributeNameProvider using external DI (by upgrading to one of the DI packages). For example, You would just need to replace the existing registration with your own. implementation This is how that would look in StructureMap, but you could just as easily use any other DI container.

this.For<IReservedAttributeNameProvider>().Use<MyReservedAttributeNameProvider>()
    .Ctor<IEnumerable<string>>("attributesToIgnore").Is(new string[0]);

I suggest for the long-term you open a new issue on GitHub. I can think of no reason why this has to be enforced across the board - this limitation of attribute names should only exist if configuring the nodes in XML, and in that case there should be no error message - just silently ignore the value. Also, the fact that MvcSiteMapNodeAttribute has this same flaw is a bad design decision that was carried over from v3. There should be a RouteValues "dictionary" (well, JSON dictionary anyway) to define values there instead of cramming everything into attributes and trying to guess which values go where. But either way, it doesn't make sense to exclude any attribute names from MvcSiteMapNodeAttribute, dynamic nodes, or custom ISiteMapNodeProvider implementations since attributes no longer update the properties or vice versa.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top