Following is a way you can achieve the above scenario. (you can find my comments in the code which describe the possible urls which hit the action).
Note that I used a inline constraint int
for the 'id' route variable. This is because we want to make sure that requests like 'Article/TestMethod' does not get captured by the route 'Article/{id?}/{*path}'. Ideally you would want to have an Order property on attribute routes to order them to avoid the scenario like above, but we removed that in the last minute and didn't have time to add it back as we wanted to make sure to do it right in terms of all scenarios. (Actually you should be facing this similar issue with your pre-attribute routing changes...could you share how your pre-attribute route configuration looks like?)
We by default order the routes where we put most specific routes before generic ones. So in the current case since the one route 'Article/{id:int?}/{*path}' has a constraint, it would be placed before the generic route 'Article/{action}' and that's the reason this is working currently.
In our next release we are re-introducing the Order property which can give you more flexibility for scenarios like this.
[RoutePrefix("Article")]
[Route("{action}")]
public class ArticleController : Controller
{
// GET /Article
// GET /Article/10
// GET /Article/10/abc/def
[Route("{id:int?}/{*path}")]
public ActionResult Index(int? id, string path)
{
return Content("Index:" + id + ":" + path);
}
// GET /Article/Articles
public ActionResult Articles()
{
return Content("Articles");
}
// GET /Article/TestMethod
public ActionResult TestMethod()
{
return Content("TestMethod");
}
}