This project is read-only.

Current route values from query string implicitly used by Url.Action<T>

Jan 16, 2014 at 8:09 PM
I've already posted this as an issue, but it was probably too vague and speculative, so I'm re-posting it here for some clarification.

The problem
MVC Futures' Url.Action<TController> allows to specify action parameters directly, as values in lambda expression, but it fails when value passed is null and its name matches query string parameter from current request - query string value is re-used instead of explicitly-stated null.

  • Current request URL: /Dummy?param=value
  • Linked action method placed in OtherController, ActionResult Index(string param)
  • Link placed on current page: Url.Action<OtherController>(null)
  • Expected generated URL: /Other
  • Actually generated URL: /Other?param=value
Null is put under the appropriate key in the RouteValuesCollection, it then goes down to Route.GetVirtualPath method, which also takes the current route values from the RequestContext. And then the evil happens - the low-level System.Web.Routing's method ParsedRoute.Bind ignores the null value and - bang - it takes the value from the current request, if any accidentally matches by the parameter name.

It means that when trying to build an URL that passes parameter "param" equal to null and the current request accidentally have parameter named also "param" (regardless of its type or existence of any logical connection), the request's "param" value will be passed instead our explicitly demanded null value. And I can see no way to pass null in this case.

See my blog post for more detailed description and solution proposal: ASP.NET MVC: Current route values implicitly used by Url.Action.

Thoughts & Questions
I know MVC Future is open source, I could submit a patch, but it will be only hiding a side-effect of some architecture decisions from System.Web and MVC. The root cause of the problem is in the design of System.Web.Routing and the behavior described can also be reached using "core" MVC URL helpers. Futures' strongly-typed variants just make it more visible and more obviously inappropriate.

I don't feel confident where would the best place to fix it.
I think such null usages in "core" MVC may be used as a feature by someone and not considered a bug; changing it would introduce potentially serious breaking change.

On the other hand, I can fix it locally in MVC Futures extensions, as proposed in the blog post linked above (by replacing RouteData instance), but it will make MVC Futures a bit inconsistent with "core" URL helpers behaviors around nulls. Would it be OK?