maartenba / MvcSiteMapProvider

An ASP.NET MVC SiteMapProvider implementation for the ASP.NET MVC framework.
Microsoft Public License
538 stars 218 forks source link

No paramaters if solution does not gets rebuild for before start #203

Closed filoe closed 11 years ago

filoe commented 11 years ago

See here for a discription: http://stackoverflow.com/questions/18174178/mvcsitemapprovider-parameters-sometimes-works-sometimes-not

In the zip file is a "working" solution which reproduces the error + a pdf document which shows you how to produce the error(Description.pdf).

Would be very, very nice if you could fix that issue as fast as possible or tell me what I've did wrong.

Zipfile: http://www.file-upload.net/download-7951847/MvcSiteMapIssue.zip.html

NightOwl888 commented 11 years ago

It is difficult to tell by your configuration what you are trying to achieve, but there are some problems I noticed:

If you decide on either "id" or "testId" and stick with it, it will work.

Please review the Routing Basics document if you haven't already as it can be helpful for setting this up.

Note that it is a little unusual to match all IDs to a single node when using nested nodes. Typically, you would have a dynamic node provider (or in this case 2 of them) generate nodes with the necessary IDs to match. Then the breadcrumb trail will appear to "remember" your last position.

filoe commented 11 years ago

You're right @NightOwl888 . I am quite new to asp and mvc. I've read and understood nearly everything you've told me. But there are two points left: The first point is your last paragraph. I don't really understand your advice. Why should I use dynamich node provider? And in reality I've got a very deep hierarchie(about 8 layers). The second point is that I have new problem. I have this hierachie(in reality -> the other code was just a very simple example):

Settlement > Section > Machine > Item >...

Lets say the user selects the settlement with id 0. Now all sections of the chosen settlement are listed. Now he selects a section with id 1. All Machines are listed. If I click on section in the SiteMapPath now the browser shows me all sections of the settlement with id 1. How can I make it keep the id 0 for the settlement?

My xml looks like this: http://s7.directupload.net/images/130812/npao98os.png I would guess it is because of the parameter id(same names). But I don't wanne create a new route for every controller.

NightOwl888 commented 11 years ago

To make it work the way you expect, you need one node per ID. The MvcSiteMapProvider can only work this way if there is a node with an ID to match. If all of your IDs match a single node (which is what you are doing), the breadcrumb trail will appear to "forget" where it was. For it to "remember" the current position, its place in the sitemap must be unique - that is, it must not match the same node as any other ID.

Have a look at #6 - there is a demo project that shows how to make 1 node per ID.

Typically, you would want your nodes with new ID to be dynamically added to the list when a new record is added to the database. That is why I suggested using dynamic node providers to achieve this result.

filoe commented 11 years ago

Hmmm but whats about the performance. There up to a few million of records in the database. I can't see any reason why not to use static sitemapnodes(see xml) which are just saving the id. Thats all I need isn't it?

btw. this also solves my problem: http://s1.directupload.net/images/130812/jxr3nna2.png But I am going to take a look at your #6 you've posted.

EDIT: I've changed my xml to this: http://s7.directupload.net/images/130812/yoy47vav.png (as you did in your sample solution in #6). But there is still the same behaviour. If the parameter in the machine node is 1 it is also 1 in section controller. @NightOwl888

NightOwl888 commented 11 years ago

preserveRouteParameters only saves the ID for the current request, not across multiple requests. The reason why your ID is wrong when clicking another node in the site map path is because one action method parameter ID has the same name as the others (also testId), and it is simply being copied over every time you request the page.

The only way to give it the appearance that it is remembering the last position is to load all of the IDs as nodes so there is only 1 node to match for a given ID and a different node for a different ID.

If you have millions of records, it might make sense to build a system that caches to the file system. We use System.Runtime.Caching.ObjectCache by default, which can be replaced by an implementation that writes to disk instead of storing it all in memory. This can be done when using an external DI container (example based on our StructureMap NuGet package):

            // Default configuration
            //this.For<System.Runtime.Caching.ObjectCache>()
            //    .Use(s => System.Runtime.Caching.MemoryCache.Default);

            // Disk file configuration
            this.For<System.Runtime.Caching.ObjectCache>()
                .Use<MyDiskFileCache>;

It might make sense to give it a try first using dynamic node providers to see just how much memory it will actually take to hold that many nodes with the default settings - the cache is shared between all users, so you will only have to worry about a single copy being cached.

Either way, you won't get the behavior you expect if there is no unique node to match.

filoe commented 11 years ago

ok thanks a lot. I am going to rename the parameters like I've already did here: http://s1.directupload.net/images/130812/jxr3nna2.png

I am also going to take a look at the ObjectCache but I don't believe in that I need a dynamic node provider because I don't use a menu. I just use the path and so I just need to store the ID.

NightOwl888 commented 11 years ago

There are only 2 ways to load the nodes from the database - using dynamic node providers or using a custom ISiteMapBuilder. This has nothing to do with using a menu, but loading your IDs into the sitemap, which is what you need to make the breadcrumbs appear to remember the path to the ancestor nodes.

NightOwl888 commented 11 years ago

Someone else wants to preserve the route values similar to the way you do. Have a look at #207.

Anyway, were you able to work this out, or is this issue still open?

NightOwl888 commented 11 years ago

I have created a blog post that goes into more detail about how to track a user's position - How to Make MvcSiteMapProvider Remember a User’s Position