Skip to content
This repository was archived by the owner on Dec 14, 2018. It is now read-only.

Unexpected Url.Action output #2859

Closed
Muchiachio opened this issue Jul 24, 2015 · 12 comments
Closed

Unexpected Url.Action output #2859

Muchiachio opened this issue Jul 24, 2015 · 12 comments
Assignees
Milestone

Comments

@Muchiachio
Copy link
Contributor

Muchiachio commented Jul 24, 2015

Given routing in beta5:

app.UseMvc(routes =>
{
    routes.MapRoute(
        name: "DefaultDouble",
        template: "{custom}/{controller}/{action}/{id?}",
        defaults: new { controller = "Home", action = "Index" },
        constraints: new { custom = "Double" });

    routes.MapRoute(
        name: "DefaultSingle",
        template: "{controller}/{action}/{id?}",
        defaults: new { custom = "Single", controller = "Home", action = "Index" },
        constraints: new { custom = "Single" });
});

And calling this from NotHome controller view

@Url.Action("Index", new { custom = "Double" })

results in

/Double

while expected output is

/Double/NotHome
@dougbu
Copy link
Member

dougbu commented Jul 24, 2015

@Muchiachio is there a typo in your sample? If not where would "NotHome" come from?

@Muchiachio
Copy link
Contributor Author

No, I just didn't want to write "Broken" in the issue 😄
I updated the sample to keep consistency.

@dougbu
Copy link
Member

dougbu commented Jul 24, 2015

@Muchiachio my point was the controller value defaults to "Home" in both routes. No route will choose the other controller.

@Muchiachio
Copy link
Contributor Author

Hmm, but you didn't need to specify other controllers in MVC5 routing, right?

@Url.Action("Index", new { custom = "Double" })

would mean, form an url for current controller and area + add custom route value/query parameter?
So if I am currently in "NotHome" controller's view, Url.Action for index should still be generated for "NotHome" controller? It seems like you need to re-specify current route values then forming an url action.

@Url.Action("Index", new { controller = ViewContext.RouteData.Values["controller"], custom = "Double" })

@rynowak
Copy link
Member

rynowak commented Jul 27, 2015

Hmm, but you didn't need to specify other controllers in MVC5 routing, right?

That depends on the current value of custom. Both old and new routing codebases have a feature that invalidates route-values when a route-value to the left (lexically, in the template) has a new value.

Ex: - using route:

routes.MapRoute(
        name: "DefaultDouble",
        template: "{custom}/{controller}/{action}/{id?}",
        defaults: new { controller = "Home", action = "Index" });

Current Values: { custom = "Double", controller = "NotHome", action = "Index" }
@Url.Action("Index", "Home", new { custom = "Double" }) should generate /Double/NotHome/Index

In this case, the current (or 'ambient') value of controller is valid, because custom has not changed.

Current Values: { custom = "Single", controller = "NotHome", action = "Index" }
@Url.Action("Index", new { custom = "Double" }) should generate /Double

In this case, the current (or 'ambient') value of controller is not valid, because custom has changed.

@Muchiachio
Copy link
Contributor Author

Does that mean that there are changes in routing in MVC6?
Because this works just fine in MVC5.

@Eilon
Copy link
Member

Eilon commented Jul 27, 2015

The same routing logic should be in MVC5 and MVC6 with respect to this...

@rynowak
Copy link
Member

rynowak commented Jul 27, 2015

The only intended behavior difference between MVC 5 and MVC 6 is that MVC 6 won't generate a link to something that doesn't exist. I'll take a look at the samples.

@rynowak
Copy link
Member

rynowak commented Jul 27, 2015

I can confirm that this is behaving differently on MVC6. Currently trying to root cause why. Thanks for the report and the helpful repos 👍

@rynowak rynowak added the bug label Jul 27, 2015
@danroth27 danroth27 added this to the 6.0.0-beta7 milestone Jul 30, 2015
@rynowak
Copy link
Member

rynowak commented Aug 13, 2015

Found the issue here. There's a piece of code in UrlHelper in MVC5 that will explicitly add the ambient values for action and controller to the 'specified values' dictionary.

http://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/RouteValuesHelpers.cs

In effect, if you call Url.Action(...) - you're never subject to route-value-invalidation for the 'typical' MVC route tokens of action and controller. area doesn't have any special behavior in this regard.

@Eilon
Copy link
Member

Eilon commented Aug 13, 2015

Ah yes I vaguely recall that.

rynowak added a commit that referenced this issue Aug 13, 2015
This change restores a link generation behavior from MVC5 and earlier
where 'action' and 'controller' values are special cased-when using
Url.Action(...).

The change is that in-effect 'action' and 'controller' are always included
in the route values given to the routing system. Passing a null value into
the Url.Action(...) method means that the ambient value for that token
should be used explicitly. This means that the 'action' and 'controller'
tokens become sticky, even when something to the lexical left in the URL
(like area) changes.
@rynowak
Copy link
Member

rynowak commented Aug 14, 2015

7aa5967

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants