1
Vote

T4MVC does not support namespaces with two of the same token

description

If I have a project with the namespace:
FooBar.FooBar.SomeProject.Web
In the *.*Controller.generated.cs files the namespace T4MVC tries to use for inheriting off controllers is wrong.
[GeneratedCode("T4MVC", "2.0"), DebuggerNonUserCode]
    public partial class T4MVC_HomeController : FooBar.FooBar.SomeProject.Web.Areas.SomeArea.Controllers.HomeController
    {
        //snip
    }
In this example, Intellisense shows the first FooBar is referring to FooBar.FooBar, so the second FooBar is actually trying to resolve to FooBar.FooBar.FooBar which doesn't exist.

comments

davidebbo wrote Feb 28, 2013 at 8:36 PM

Not sure I understand. The namespace you show in the generated code looks correct, no?

Though I would add that having the same token appear twice in the namespace is generally not recommended as it often leads to ambiguous code.

elwynelwyn wrote Feb 28, 2013 at 9:22 PM

The full namespace seems to be generated correctly, yes, but I get a compile error
The type or namespace name 'FooBar' does not exist in the namespace 'FooBar.FooBar' (are you missing an assembly reference?)
With the error referring to the second 'FooBar' (which Visual Studio highlights red, and says "Cannot resolve symbol FooBar")
If I hover over the first FooBar token, I get "namespace FooBar.FooBar"

I get the same thing if I create a new MVC project with a double token namespace and plug in T4MVC.

It seems like an edge case where a double token at the start of a namespace needs to be reduced to a single token.

I'm not able to change the namespace, the double token is MyCompany.MyCompany (my companies flagship product is the same as the company name, hence the double token)

elwynelwyn wrote Feb 28, 2013 at 9:35 PM

Steps to reproduce:
  • Create new empty MVC web application
  • Right click the project, and go to Properties, and change the Default Namespace to have a double token, for example change it to "Test.Test.MvcApplication1"
  • Add a test Controller (so it should be in namespace Test.Test.MvcApplication1.Controllers)
  • Install T4MVC nuget package (and T4MVCExtensions dependency)
  • Click Build -> Transform All T4 Templates
  • Now click Build -> Build Solution
At this point you will get the compilation errors I have described

davidebbo wrote Feb 28, 2013 at 10:26 PM

Turns out this same issue came up recently in this thread. There was a possible fix there, but the person didn't follow up on it.

You could try that direction, or you can try the global:: approach. Specifically, try changing line 321 to:
    public partial class <#=controller.DerivedClassName #> : global::<#=controller.FullClassName #>
I just added the global::

elwynelwyn wrote Feb 28, 2013 at 11:36 PM

Thanks David, that did the trick nicely (I went with the global:: approach)

elwynelwyn wrote Mar 1, 2013 at 12:24 AM

I should also note I had to make a change to line 1592, for the types being generated for parameters.

I changed this:
TT.Write(p.Type + " " + p.Name);
To this:
if (p.Type.StartsWith("FooBar"))
    TT.Write("global::" + p.Type + " " + p.Name);
else
    TT.Write(p.Type + " " + p.Name);
Not ideal hardcoding my namespace in like that but it does the trick

davidebbo wrote Mar 1, 2013 at 1:22 AM

Right, it starts making the generated code dirty. If you look at that thread, the proposal thread was trying to avoid that by:
  • Adding using namespaces in the generated file
  • Using the short class name when within those namespaces