Martin Djonov
Martin Djonov

Reputation: 43

MVC SiteMap parent parameters not preserved

I am having the following problem. I setup MVC SiteMap but there is a node which I need to save (preserve) the parameter. Technically the problem explained:

I have route: Agent/Checklists/Templates, from there I am opening specific template, Agent/Checklists/EditTemplate/1 (where 1 is the id) Then from there I am opening new page which is Agent/Processes/Add

In the last page I have the breadcrumb: Templates > Edit Template > Add Process

And now I want when I click on Edit Template to get me redirected to Agent/Checklists/EditTemplate/1

I tried putting SiteMapPreserveRouteData decorator on the Action but it says it is obsolete.

Here is my Mvc.sitemap

<mvcSiteMapNode title="Templates" controller="Checklists" action="Templates" area ="Agent">
        <mvcSiteMapNode title="Edit Template" controller="Checklists" action="EditTemplate" area="Agent" preservedRouteParameters="id">
          <mvcSiteMapNode title="Add Process" controller="Processes" action="Add" area="Agent" preservedRouteParameters="id, id" />
          <mvcSiteMapNode title="Process Configuration" controller="Processes" action="Edit" area="Agent" preservedRouteParameters="token" />
        </mvcSiteMapNode>
      </mvcSiteMapNode>

Thanks

Upvotes: 1

Views: 1145

Answers (1)

NightOwl888
NightOwl888

Reputation: 56849

Preserved route parameters are preserved from the current request. Therefore, each route key must be unique within the same node ancestry. In other words, when using preservedRouteParameters you cannot reuse id again for a different purpose (different entity).

Using preservedRouteParameters, the id route value will only work for one level. If you nest levels deeper than that, you will need to create a unique route key for each level.

And you do need to ensure you preserve the parameters of the parent node for every ancestor, or the URL won't be constructed correctly.

<mvcSiteMapNode title="Templates" controller="Checklists" action="Templates" area="Agent">
    <mvcSiteMapNode title="Edit Template" controller="Checklists" action="EditTemplate" area="Agent" preservedRouteParameters="checklistId">
        <mvcSiteMapNode title="Add Process" controller="Processes" action="Add" area="Agent" preservedRouteParameters="processId,checklistId" />
        <mvcSiteMapNode title="Process Configuration" controller="Processes" action="Edit" area="Agent" preservedRouteParameters="token,processId,checklistId" />
    </mvcSiteMapNode>
</mvcSiteMapNode>

A simple way to manage this is to add a route per controller.

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

        routes.MapRoute(
            "Checklists",
            "Checklists/{action}/{checklistId}",
            new { controller = "Checklists", action = "Index", checklistId = UrlParameter.Optional });

        routes.MapRoute(
           "Processes",
           "Processes/{action}/{processId}",
           new { controller = "Processes", action = "Index", processId = UrlParameter.Optional });

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

Then you need to add the ancestry data to each URL.

@Html.ActionLink("Edit Process", "Edit", "Process", new { token = "1234", processId = "5678", checklistId = "23" } , null)

See these demos for samples of using both preservedRouteParameters and dynamic node providers.

Upvotes: 1

Related Questions