1

Closed

Attribute routing should support {action} in route for DRY

description

We should be allosed to use the {action} token when specifying routes so we do not have to repeat the method name everywhere...

Current:
    [Route("SomeSuperAction/{id:int}")]
    public virtual ActionResult SomeSuperAction(int id)
    {
Proposed:
    [Route("{action}/{id:int}")]
    public virtual ActionResult SomeSuperAction(int id)
    {
Closed Feb 11 at 7:20 PM by nowakra

comments

kichalla wrote Feb 10 at 5:17 PM

It feels odd to use parameter variable like 'action' on an action which is decorated with attribute route. Not sure if you are aware of this but we do support controller-level routes..for example, in the below scenario the controller level route applies to all actions
   [Route("Home/{action}")]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

        public ActionResult Contact()
        {
            ViewBag.Message = "Your contact page.";

            return View();
        }
    }
For MVC and its action based approach, i think this should cover majority of scenarios..do you agree?

WayneBrantley wrote Feb 10 at 5:57 PM

So, if I specify the controller level route, how do I then specify parameters?
How would I handle a SomeSuperAction(id int) method and map that parameter on the URL without an {action} token?

It also feels really odd to have to type the text of the same exact method name when it is an attribute.
   [Route("Home/{action}")]
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult About()
        {
            ViewBag.Message = "Your application description page.";

            return View();
        }

       [Route("{action}/{id:int}")]  //How can I do this?
        public ActionResult  SomeSuperAction(int id)
        {
            return View();
        }
    }
Thoughts?

nowakra wrote Feb 11 at 7:20 PM

We intentionally don't support the use of {action} as a parameter to prevent confusion. What you're suggesting is one coherent way that {action} could work in attribute routes, but without special logic to in the framework to support it, a scenario like:
       [Route("{action}/{id:int}")]  //How can I do this?
        public ActionResult  SomeSuperAction(int id)
        {
            return View();
        }
would match "/5", "SomeSuperAction/5", and "SomeOtherAction/5". The match for "/5" is possible because the {action} parameter already carries with it a default value of 'SomeSuperAction' in this case, which is needed to do the correct thing in URL generation.

However, this behavior is customizable via IDirectRouteFactory. You can create your own attribute to replace [Route] that implements the logic you want.

This should do what you're asking for, just use [ActionRoute] instead of [Route]
using System;
using System.Linq;
using System.Web.Mvc.Routing;

namespace MVCTesting
{
    [AttributeUsage(AttributeTargets.Method)]
    public class ActionRouteAttribute : Attribute, IDirectRouteFactory
    {
        public ActionRouteAttribute(string template)
        {
            Template = template;
        }

        public string Template
        {
            get;
            private set;
        }

        public RouteEntry CreateRoute(DirectRouteFactoryContext context)
        {
            var action = context.Actions.Single();

            // replace the {action} token in the url template with the actual action name
            var replaced = Template.Replace("{action}", action.ActionName);

            var builder = context.CreateBuilder(replaced, null);
            return builder.Build();
        }
    }
}

WayneBrantley wrote Feb 12 at 3:53 AM

I fail to see how this causes confusion, but if you do not want to make the frameworks support this, it is easy enough to add support myself as you have shown.

Thanks.