Frage

Setup:

I am using MvcSiteMap version 3 in an ASP.NET MVC 4 app.

Problem:

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.

What seems to be happening:

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?!

Note (and questions restated):

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.

War es hilfreich?

Lösung

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:

  1. Use named routes to ensure that only the route you want will get used to generate the URL (this is often a good practice, though it won't help in this particular scenario)
  2. Specify all route parameters explicitly - even the values that you want to be empty. That is one way to solve this particular problem.
  3. Instead of using Routing to generate the URLs, you can use Razor's ~/ syntax or call Url.Content("~/someurl") to ensure that no extra (or unexpected) processing will happen to the URL you're trying to generate.

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.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top