I am using MvcSiteMap version 3 in an ASP.NET MVC 4 app.
I have a node like this:
<mvcSiteMapNode title="Neighbours" area="MilkyWay" controller="SolarSystems" action="Planets" key="neighbours">
The Planets
action on the SolarSystems
controller has two parameters, int order, int size
, where order states the order of the planets starting from the star. Eg, Mercury
would be 1
, and size is the order of the planets by size, where the smallest is 1
.
For both parameters, -1
means I don't have a clue.
In my route registration, I have something like:
context.MapRoute(
"SolarSystems_Planets",
"SolarSystems/Planets/{order}/{size}",
new { controller = "SolarSystems", action = "Index", order = -1, size = -1 }
);
All works OK, ie, the default values are used...
...EXCEPT when the current page is an action that has the same two parameters with the same names.
In that case, the node will use these two parameters instead of the default values of -1.
For example, If I have a GalaxyClusters
controller with an Index
action that has two parameters int order and int size
, and in the current request, order == 10009985639 and size = 9098 then my planets action tries to find a planet in our solar system with those values.
Obviously, it will fail and we have known that since Galileo's days.
In other words, it seems that MvcSitemap injects the current values of any parameter and if a match is found, then BOOM! This seems wrong to me, so is this the default?
The problem is easily solved by putting in the node the following:
<mvcSiteMapNode title="Neighbours" area="MilkyWay" controller="SolarSystems" action="Planets" order="" size="" key="neighbours">
Is this reliable?!
I know I have answered what might appear to be my question, but if you think that, before voting to close the question, please read it carefully:
The question I am asking is whether this is the default behaviour? If it is, why? And: is my solution reliable?
Finally, I don't really have an app that catalogs all the galaxies in the Universe (sql server might not like that many records and I would be in receipt of the Nobel prize). I just adapted the problem so that I don't use my client's domain names.
This behavior is not part of MvcSiteMapProvider, but part of the MVC UrlHelper class and they don't intend to fix it.
According to the issue that was submitted about this to the MVC team, this behavior is by design. That is, the URL generation code will pick up ambient values of the request and automatically inject them into the URL if they match.
Their advice about how to work around this issue are the following:
You can accomplish all 3 of these solutions with MvcSiteMapProvider.
<!-- Using a named route -->
<mvcSiteMapNode title="Neighbours" area="MilkyWay" controller="SolarSystems" action="Planets" route="SolarSystems_Planets" key="neighbours">
That won't help in your case, but I am including it here to demonstrate how it can be done.
<!-- Specify parameters explicitly -->
<mvcSiteMapNode title="Neighbours" area="MilkyWay" controller="SolarSystems" action="Planets" order="10009985639" size="9098" key="neighbours">
This means of course you will need a node for each combination of order and size. If the data is coming from some shared resource such as a database, you can implement IDynamicNodeProvider to create a node for each case. This of course assumes that you know in advance what all of the potential values will be.
<!-- Specify the URL explicitly -->
<mvcSiteMapNode title="Neighbours" url="/MilkyWay/SolarSystems/Planets/10009985639/9098" key="neighbours">
Again, you will need a node per URL to accomplish this successfully.
See the issue @ GitHub about this for further details.