2

Closed

Constant strings instead of readonly

description

You cannot use anything generated by T4MVC in Attributes, because they require constant expressions, defined at compile-time. But this feature is important to avoid magic strings in attributes.

A similar discussion with a sample implementation:
http://stackoverflow.com/questions/6470659/no-constants-generated-by-t4mvc
...but it doesn't allow the MVC.ControllerName.ActionName mechanism.

file attachments

Closed Dec 7, 2011 at 7:21 AM by davidebbo
I just pushed 2.6.65 to nuget with that change.

comments

davidebbo wrote Nov 29, 2011 at 5:58 PM

What holds me back a bit is that there would then be two different ways of accessing those strings: one via MVC.*, and this new one via the full controller class name. Would be nice to find some solution that avoids this, though I'm not sure if there is one.

bugmenot2 wrote Nov 30, 2011 at 2:56 AM

Not having the "MVC.*" syntax is a pity. But if it's a choice between that and using magic strings, I'll take the former.

There are undoubtedly many who like me, want this functionality, so I refactored that StackOverflow implementation as it was a bit off. Could you please tell me if the additions below are ok, or if I should improve on them? It "seems to work", but I don't understand the innards of the T4MVC template, and so hesitate to use my patch.

To add const controller names:
    [<#= GeneratedCode #>]
    public readonly string Name = "<#=ProcessAreaOrControllerName(controller.Name) #>";
    [<#= GeneratedCode #>]                                                                                                          // ---------- add this
    public const string NameConst = "<#=ProcessAreaOrControllerName(controller.Name) #>";         // ---------- add this
To add const action names:
    public class ActionNamesClass {
<#foreach (var method in controller.ActionMethodsWithUniqueNames) { #>
<# if (UseLowercaseRoutes) { #>
        public readonly string <#=method.ActionName #> = (<#=method.ActionNameValueExpression #>).ToLowerInvariant();
        public const string <#=method.ActionName #>Const = (<#=method.ActionNameValueExpression #>).ToLowerInvariant();         // ---------- add this
<# } else { #>
        public readonly string <#=method.ActionName #> = <#=method.ActionNameValueExpression #>;
        public const string <#=method.ActionName #>Const = <#=method.ActionNameValueExpression #>;                                      // ---------- add this
<# }
} #>
    }
This gives, say:
T4MVC_CarController.NameConst // const name for the "Car" controller
T4MVC_CarController.ActionNamesClass.IndexConst // const name for the "Index" action

davidebbo wrote Nov 30, 2011 at 7:11 AM

Could you attach the complete file to the issue, so I don't have to hand merge. :) I may not be able to look at it for a couple days, but if it looks harmless I'll try to get it in. Thanks!

bugmenot2 wrote Nov 30, 2011 at 10:49 PM

Cool, would be nice to have in main template. Attached.

rroesler wrote Dec 5, 2011 at 6:47 PM

In fork rroeslerpatch1 I tried to solve this by creating Links.Views and Links.Actions containing only const strings

davidebbo wrote Dec 6, 2011 at 8:01 AM

Finally looking at this. I think I'll go with a variant on what @bugmenot2 attached: instead of adding the constants to the same ActionNamesClass, create a separate class with cleaner names. e.g. instead of
    [Dummy(ActionNamesClass.IndexConst)]
you'd have
    [Dummy(ActionNameConstants.Index)]
Which looks a little less quirky. Does that work for you?

@rroesler sorry, haven't looked at your change yet.

bugmenot2 wrote Dec 6, 2011 at 9:56 AM

Frankly both your suggestion and that of @rroesler seem clean. So whatever is easier to maintain seems best.

bugmenot2 wrote Dec 7, 2011 at 3:41 PM

awesome thanks

davidebbo wrote Dec 22, 2011 at 6:22 PM

Darn, this breaks the UseLowercaseRoutes case because you can't use ToLowerInvariant() in a constant expression (http://stackoverflow.com/questions/8605868/t4mvc-2-6-65-and-uselowercaseroutes-true-error). I need to revisit this fix.

kkara wrote Jan 4, 2012 at 5:45 PM

Is there a way to access through constants the view names as well? I can't find a ViewNameConstants anywhere. If there isn't a way is there a reason for that?

davidebbo wrote Jan 4, 2012 at 6:25 PM

@kkara: not currently. Is there a specific scenario where this is needed and readonly won't work? If so, please open a separate issue to track.

davidebbo wrote Sep 3, 2012 at 9:00 AM