Absolutely, it's useful for REST-style routing with nested resources.
So right now I have a project where Users can have many Websites. Each Website in turn has a ton of model objects associated with it (Events, Posts, etc). So I get routes like:
GET /websites/:websiteId/events controllers.websites.Events.list(websiteId, page:Int ?= 0)
The handler for this action then looks like:
object Events extends WebsitesControllerBase {
def list(
websiteId : String, page: Int) = WebsiteAdminAction(websiteId)(website => implicit request => {
new ListPage(website, page, Event.paginateEx(page, where = Seq("websiteId" -> website.id.get)))
})
}
Where as you pointed out in your earlier post, the websiteId needs to be passed into a custom Action (marked in red) that thereby has access to it - otherwise it can't fetch & authorize access to the website.
Note that there is now a categorical difference between the "page" parameter and the "websiteId" parameter since one is available through the queryString and the other is not, which leads to this non-uniform access. Yes, the workaround works (it is in fact what I'm using now), but it's indicative that something is not ideal.
I suggest two things:
1.a Add a parameters:Map[String, Seq[String]] to RequestHeader that gets *all* the parameters associated with the request (much like FormUtils does for Form.bindFromRequest). As a consumer of the framework I really don't care where the parameter came from - Do What I Mean (DWIM), not what I said.
1.b Yes, the HTTP spec certainly allows multiple entries for the request parameters, but it is *very* rarely used in practice. So a better signature might be:
parameters:Map[String, String] and parametersWithMultipleEntries:Map[String, Seq[String]] where the latter is only parsed if asked for (and it also penalizes use like .asInstanceOf[OtherClass] does).
2. For the routing, could one do a reverse route with two parameter lists? I.e.
GET /foo/:bar controllers.Application.foo(gazonk)
would result in a reverse route like so:
controllers.routes.Application.foo(gazonk)(bar)
That probably breaks a lot of internal assumptions, but it would work nicely from a user-of-framework perspective.