mccalltd / AttributeRouting

Define your routes using attributes on actions in ASP.NET MVC and Web API.
http://mccalltd.github.io/AttributeRouting/
MIT License
416 stars 89 forks source link

Cannot have default values in AreaUrl or RoutePrefix #211

Closed Bitsonthefloor closed 11 years ago

Bitsonthefloor commented 11 years ago

If you use default values and constraints in either AreaUrl or RoutePrefix, the constraints will be passed into the resulting route but any default values will not. It seems to be because CreateRouteConstraints in RouteBuilder uses BuildTokenizedUrl where CreateRouteDefaults only uses routeSpec.RouteUrl

mccalltd commented 11 years ago

Default values will only work when the url has no static section following the param (following the rules for optionals, as the default is only used if the param has no value). Constraints work anywhere.

"{p1=default}/static" // this won't work
"{p1=default1}/{p2=default2}" // this will work if the params are not given, yielding "default1/default2"
Bitsonthefloor commented 11 years ago

It is not that the defautls are not working, its that the code is not parsing the defaults out of the url, DefaultValues are only parsed from the routes specified RouteUrl, whereas Constraints are parsed from the url built from the BuildTokenizedUrl. This is mostly useful for url building (i.e. enforcing default values in a RouteUrl method).

Bitsonthefloor commented 11 years ago

An example: Lets say I have [RouteArea("Api", AreaUrl="Api/{version:decimal=1.0}")]

The expected output when Url.RouteUrl([some action]) would be /Api/1.0/[some action], however because the DefaultValues of the route does not have the 1.0, unless the 1.0 is specified as a value in a dictionary, the result is a null since no route matched.

mccalltd commented 11 years ago

Ah, I see now. Thanks for reporting.

mccalltd commented 11 years ago

Hmm, actually what you showed me will suffer from the problems I mentioned above. Defaults, to my knowledge, don't work when they are between static sections. I'll mess around a bit to try and repro.

Bitsonthefloor commented 11 years ago

Here is an example to try:

[RoutePrefix("Controller/{version:decimal=1.0}")] public class ControllerTestController : Controller {

[GET("{param:long=1}/Action")] public ActionResult TAction() { return View(); }

}

If you look at the route created it will have an entry in Constraints but no entry in DefaultValues for version, but param will have an entry in both. in a view if you do the following:

@Url.Action(new { controller = "ControllerTest", Action = "TAction" }) @Url.Action(new { controller = "ControllerTest", Action = "TAction", version = "1.0" })

The first Url.Action will not match, but the second will, though both should match and return Controller/1.0/1/Action

Bitsonthefloor commented 11 years ago

what your thinking of is when the routing engine is parsing a url and in that situation the {version} would not match when missing because the url parser would expect a value between the two statics, it can only handle missing values on the end.

mccalltd commented 11 years ago

Fix available in 3.5.3.