This project is read-only.

FromRoute token name

Dec 26, 2011 at 11:46 AM

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.

Dec 27, 2011 at 12:24 AM

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.

Dec 27, 2011 at 10:53 AM

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?

Dec 27, 2011 at 9:09 PM
Looks good, I'm trying it right now.
Dec 28, 2011 at 4:41 AM
Done, see latest revision.
Dec 29, 2011 at 3:49 PM

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