Problem with Razor @helper method (Solved)

Oct 26, 2011 at 12:58 AM

In my compiled library (which started with an new Empty MVC3 Project), I have an @helper template defined in a file named MyTemplates.csthml in the App_Code folder.

@* Generator: MvcHelper *@

@helper AAEcho(string message) {
    
    @message

}

But I am not able to use it in my view... with the compile error "The name 'MyTemplates' does not exist in the current context"

@{
    ViewBag.Title = "Test Helper Template";
}

@MyTemplates.AAEcho("Hello from AAEcho")

The generated code looks okay...

    [System.CodeDom.Compiler.GeneratedCodeAttribute("RazorGenerator", "1.2.0.0")]
    public static class MyTemplates
    {

public static System.Web.WebPages.HelperResult AAEcho(string message) {...}

I've tried modifying the namespace emitted by the razor generator using the Custom Tool Namespace. I tried just the project name, project name.app_code and the project.areas.areaname.views.viewname to match where the views are with no luck.

I've tried with TypeVisibility set to both internal and public as well as not at all.

I've tried with Generator set to MvcHelper and MvcView.

I've tried making the template into an HtmlHelper extension also with the same results...

Thanks for any advice.

 

 

 

 

 

 

Coordinator
Oct 26, 2011 at 1:39 AM

The problem is that in design time, the view pages are generated under an entirely different namespace (named ASP) so the designer has no idea where your helper is. You should be able to reproduce this issue by creating a class in the root namespace of your MVC application and trying to reference it in your view without qualifying it. Runtime works correctly since your helper is presumably along the namespace path.

A simple workaround is to include the Helper's namespace via the system.web.webPages.razor\pages\namespaces section in the web.config located under Views or add a @using <HelperNamespace> in your view page. Again, this is solely meant to provide design time support, you should be able to compile your page without these but VS is a lot less fun without intellisense.

Oct 26, 2011 at 2:13 AM

Thanks for the explanation as well as the workaround. I found that having the HelperNamespace in the Views\web.config did not work for my project; however, I was able to do this...

  1. Put the MyTemplates.cshtml file in a folder Views\Helpers (left Generator directive out altogether).
  2. Modify the Custom Tool Namespace to ProjectName.Helpers
  3. Add @using ProjectName.Helpers to the view
  4. Call @MyTemplates.Echo("Hello") from the view

For some reason having the namespace (ProjectName.Helpers) added to the web.config did not seem to make a difference at run time or design time.

Thanks again!

 

Coordinator
Oct 26, 2011 at 5:01 PM

Out of curiosity, does adding the helper namespace to web.config result in the namespace being used in the generated file (via a "using ProjectName.Helper;")? If not it might be a bug in our generator.

Oct 26, 2011 at 11:10 PM

No it doesn't add a using to the generated code.

Feb 15, 2012 at 3:19 AM
Edited Feb 15, 2012 at 3:19 AM

I ran into this problem today - using razorgenerator on both helper and view, the generated view could not resolve the generated helpe.  

We'd attempted to some, possibly outdated, advice from ScottGu about using an app_code directory....

Much scratching of heads...

...which was finally solved when it became clear that the helper.generated.cs was set to 'content' not 'compile'.

So, is this a bug?  To reproduce:

 

Create 'bad. cshtml' file in the app_code directory

Add CustomTool 'RazorGenerator' to 'bad.cshtml'

Actual properties of bad.generated.cs:

   Build Action: 'Content'

Expected properties of bad.generated.cs:

  Build Action: 'Compile'

Coordinator
Feb 15, 2012 at 7:12 AM

Ah yes, VS defaults sources files that live in App_Code to Content, as that's generally what you want. I'd say that if you're going to use RazorGenerator, you have no reason to use App_Code at all. App_Code is specifically for sources that you want compiled at runtime, while RazorGenerator is about compiling things at build time with the rest of your main assembly.

But if you really want to put those in App_Code, then yes, changing the build action is the way to go. I'm not sure whether this is something that RazorGenerator could automatically do itself, but it might be worth investigating.