开发者

ASP.NET MVC 2 RC2 Routing - How to clear low-level values when using ActionLink to refer to a higher level?

开发者 https://www.devze.com 2022-12-24 14:40 出处:网络
[NOTE: I\'m using ASP.NET MVC2 RC2.] I have URLs like this: /customers/123/orders/456/items/index /customers/123/orders/456/items/789/edit

[NOTE: I'm using ASP.NET MVC2 RC2.]

I have URLs like this:

/customers/123/orders/456/items/index

/customers/123/orders/456/items/789/edit

My routing table lists the most-specific routes first, so I've got:

// customers/123/orders/456/items/789/edit
routes.MapRoute(
    "item", // Route name
    "customers/{customerId}/orders/{orderId}/items/{itemId}/{action}", // URL with parameters
    new { controller = "Items", action = "Details" }, // Parameter defaults
    new { customerId = @"\d+", orderId = @"\d+", itemId = @"\d+" } // Constraints
);

// customers/123/orders/456/items/index
routes.MapRoute(
    "items", // Route name
    "customers/{customerId}/orders/{orderId}/items/{action}", // URL with parameters
    new { controller = "Items", action = "Index" }, // Parameter defaults
    new { customerId = @"\d+", orderId = @"\d+" } // Constraints
);

When I'm in the item "Edit" page, I want a link back up to the "Index" page. So, I use:

ActionLink("Back to Index", "index")

However, because there's an ambient item ID, this results in the URL:

/customers/123/orders/456/items/789/index

...whereas I want it to "forget" the item ID and just use:

/customers/123/orders/456/items/index

I've tried overriding the item ID like so:

ActionLink("Back to Index", "index", new { itemId=string.empty开发者_如何转开发 })

...but that doesn't quite work. What that gives me is:

/customers/123/orders/456/items?itemId=789

How can I persuade ActionLink to "forget" the item ID?


EDIT: fixed question - I was referring to "order" where I meant "item".

EDIT: added detail of why itemId=string.empty doesn't work.


In your constraint you can delete any routeValues you do not need.

values.Remove("itemId");

Then create a class that inherits from IRouteConstraint.

Then in the Match method clear your route value and return true (indicates the route matches).

public bool Match(HttpContextBase httpContext, Route route, string parameterName, RouteValueDictionary values, RouteDirection routeDirection)
{

    values.Remove("itemId");    
    return true;
}

then in Global.asax.cs change

new { customerId = @"\d+", orderId = @"\d+" }

to

new { customerId = @"\d+", orderId = @"\d+", custom=new MyNewConstraint() }


I deleted my previous answer, didn't notice they were the same controller. Try setting itemId = string.empty. This will make the first route fail, as it requires a digit in that position.

ActionLink("Back to Index", "index", new { itemId=string.empty })

Optionally you can create a link with the name of the route "item" manually

<%= Url.RouteUrl("item", new { controller="Items", action="Index", orderId=3 ... }) %>


OK, I think I've got this to do what I want, by using RouteLink instead of ActionLink:

RouteLink("Back to Index", "items", new { action="index" })

...where the 2nd parameter is the name of the route I want to explicitly invoke.


EDIT: I didn't really want to go through all my dozens of ActionLinks and put them in this form, so instead I've modified the "item" rule to include a constraint on the {action} parameter, so that "index" does not match this route. Thus, it matches the "items" route instead - which has no itemId parameter. That seems to be a simpler way to do this, since the bulk of my code is unchanged.


Solution at the root of the problem

It seems that the optimal solution (that doesn't smell like a workaround) is the one that solves the problem where it has roots and that's in routing.

I've written a custom Route class called RouteWithExclusions that is able to define route value names that should be excluded/removed when generating URLs.

The whole problem is detailed and explained in my blog post and all the code is provided there as well. Check it out, it may help you solve this routing problem without the use of constraints but with a route that does what's required.

0

精彩评论

暂无评论...
验证码 换一张
取 消