View names cannot be used in attributes because they are not constants


I'm attempting to use the HandleError attribute like this:
[HandleError(ExceptionType = typeof(ItemNotFoundException), View = MVC.Shared.Views.ErrorPages.ItemNotFound)]
This results in the following compile error:
"An attribute argument must be a constant expression..."

The reason is that T4MVC generates readonly fields rather than constants for view names (such as "ItemNotFound" in this example).

I'd like to suggest that you use constants instead. If there is a good reason why you are not using constants, is there some way to generate an alternate set of view names that use constants? Or perhaps make it an option in the settings?
Closed Jan 28, 2015 at 3:12 PM by KevinKuszyk
As part of our move to GitHub, we are closing all the outstanding issues on CodePlex.

If your issue is still valid, please re-open it on GitHub:

Thanks for contributing!


davidebbo wrote Sep 2, 2012 at 9:37 PM

danthman wrote Sep 2, 2012 at 11:15 PM

Hi David,

I did a search here but didn't think to check the issues on the main MVCContrib site.

Anyway, I'm assuming @kkara never did end up opening a separate issue for view names (at least I can't find it via search).

davidebbo wrote Sep 3, 2012 at 8:08 AM

Indeed, no bug was filed fro that so it's good to have it.

But note that the reason these are not constant is actually quite different from the action name case covered by that other bug.

For view names, the reason is in fact that the value is not a true constant. Instead, it calls ProcessVirtualPath which computed the right path (and can be user modified - see settings.t4 file).

So I'm all for the idea, but we need to find a way to make this work well.

danthman wrote Sep 3, 2012 at 10:39 PM

I'm probably confused or missing something, but looking at the generated code in my project, it seems like ProcessVirtualPath is only used during run time with stuff in the Content folder (scripts, images, etc.). The view paths seem to be created at "generate time", not during run time.

Here's the generated code for the ItemNotFound view:
public readonly string ItemNotFound = "~/Views/Shared/ErrorPages/ItemNotFound.cshtml";

It seems like you would simply need to replace "readonly" with "const" in the generator code (looks like the ProcessStaticFilesRecursive() method).

davidebbo wrote Sep 4, 2012 at 1:05 AM

My bad, I was thinking content path. :)

For View names, the situation is more similar to what it is for action names, and it cannot just be changed. Otherwise, you won't be able to write something like MVC.Home.Views.Index, since that relies on an instance chain (so it can't be constant).

But it may be possible to support a parallel class containing constants like we did for action names. Feel free to give this a try and send a pull request if you get something working well (and in a non-breaking way).

cwe1ss wrote Apr 11, 2014 at 10:19 PM

Hi David,

I added support for this in a fork. It generates a "ViewConstants"-class for every controller, quite similar to the "ViewsClass".

However, I'm not sure if it's really good to add this, since the syntax is quite verbose (see unit tests) and it seems like demand for it is quite small. Of course, we could add a config-switch for it, but this would make the config more complex.

I'm also not sure how to best handle shared views and views from non-existing controllers. It's a little bit weird to reference them with a Controller from the T4MVC-namespace. So maybe these views shouldn't be supported at all for this scenario?!

I don't need this feature for one of my projects, I just implemented it for fun! :) So just tell me what you think about it and whether I should finish working on it.

here's the link to the fork:

regards, christian