FromRoute token name

Imported from the CodePlex archive for reference purposes. Support for MvcCodeRouting has ended.

Commented on

Now, token name is equal to public property name marked with FormRoute. Token name is not impotant for simple data bind to controller property.

But, in my application route data should be accessed outside of controllers (filter attributes, some context classes and so on). Next, token name used in url building process - and there is a trouble. For most tokens I'm use camel-style, but my company code convention use pascal-style for public properies.

I think that "TokenName" property in FormRouteAttribute is good idea.

Commented on link

Yes, this would be a nice feature. It is however low priority, because it's not a blocking issue, there are workarounds, and it's not supported by ASP.NET MVC so it will require some hacking to make the modelbinder/valueprovider use a name different from the parameter/property name.

Commented on link

Hacking of MVC classes is not required - just give them what they want :)

There is a 4 simple steps:

1) Add string TokenName property to FromRouteAttribute.

2) Change last line in ControllerInfo to use TokenName instead of property name (if present):

return new TokenInfo(routeAttr.TokenName ?? property.Name, constraint);

3) Before call to DefaultBinder.BindModel in CodeRoutingExtensions, duplicate bindable data with property name as key:

         var replacements = controller.GetType()
             .GetProperties()
             .Select(pi => pi.PropertyType)
             .Where(pt => pt.IsDefined(typeof(FromRouteAttribute), true))
             .Select(pt => new
                             {
                                 pt.GetCustomAttributes(typeof(FromRouteAttribute), true).Cast<FromRouteAttribute>().Single().TokenName,
                                 PropertyName = pt.Name
                             })
             .Where(x => !string.IsNullOrEmpty(x.TokenName))
             .ToDictionary(x => x.TokenName, x => x.PropertyName);

          foreach (var keyValuePair in replacements)
          {
            controller.ControllerContext.RouteData.Values[keyValuePair.Value] =
                  controller.ControllerContext.RouteData.Values[keyValuePair.Key];
          }

4) After call to DefaultBinder.BindModel, remove useless data from dictionary:

         foreach (var uselessKey in replacements.Values)
         {
             controller.ControllerContext.RouteData.Values.Remove(uselessKey);
         }

What do you think about my solution?

Commented on link
Looks good, I'm trying it right now.
Commented on link
Done, see latest revision.
Commented on link

Thank you again, all works fine. Now my project use only MvcCodeRouting for create routes.