Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get Visual Studio to highlight Razor syntax with a custom host factoryType

Here's the scenario, I've extended MvcWebRazorHostFactory so I can do a little bit of extra view magic at build time. The exact magic doesn't matter.

The registration in my ~\Views\Web.config looks like so:

<host factoryType="StackExchange.MyNamespace.MyFactory, StackExchange.MyNamespace" />

There's to the appropriate assembly in the project, a copy of the assembly in a \lib folder, and I've confirmed that it's copied to \bin as expected. Furthermore, the actual view magic does happen when views are built so ASP.NET itself is actually finding everything.

What doesn't work in Visual Studio (2012)'s Razor Syntax Highlighting.

enter image description here

Above is a snapshot of how the syntax highlighting fails. As a rule, anything not in a namespace directly @using'd cannot be found (and thus gets the red squiggly underline) and the @model directive doesn't works. This points to some trouble getting at our automatically included namespaces in the Web.config.

The tooltip for the error on @model is "The name 'model' does not exist in the current context".

Through trial and error I've narrowed the root cause to the above host config section, although we have some other tweaks around Razor (a custom pageBaseType for example) it's that one line that breaks everything.

Things I've tried thus far:

  • Strong naming the assembly
  • Installing the assembly in the GAC
    • This page hints at this being necessary.

When strongly named my ~\Views\Web.config ended up looking like so:

<host factoryType="StackExchange.MyNamespace.MyFactory, StackExchange.MyNamespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b61d663b67b05bd2" />

I checked the Version, Culture, and PublicKeyToken against the GAC using "gacutil -l".

I suppose one other possible point of failure is the GAC itself, as there are ton of .NET versions on my box. Both the assembly and the web site are built with .NET 4.5 (both referencing MVC 4, Razor 2, and so on). The path to the gacutil I've been using while debugging is Program Files (x86)\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools\gacutil.exe.

Occasionally during my winnowing to a root cause I'd get an error message to the effect "StackExchange.MyNamespace.MyFactory could not be found" on the first line of a view. The underline would be in the "Other Error" color (Purple in VS2012 Dark Theme). I could not reliably reproduce that, so I can't get a screenshot.


So my question is, does anyone know how to get Visual Studio (2012 again) to properly handle Razor Views with a custom host factory?

My current best guess at a fix is doing some really hacky Web.config replacements so I have one config while editing and another while debugging. Really not a fan of that idea though.

It seems like this should work, and that Visual Studio is just having troubling finding something it needs. I just don't know what that is.


Update after some more experimentation.

I've got more developers to reproduce that it's the <host pageFactoryType="...">, including in a vanilla MVC4 application (the above examples are, somewhat obviously, from the StackOverflow solution; which might have had some cruft).

We have found a work around though, it's to buy a ReSharper license. Not a great (or cheap) work around, but a work around none the less.

With ReSharper installed everything works with one caveat. If you have a custom <pages pageBaseType="..."> registration the type must be in the same project, or you don't get intellisense for @this.Model reference (the @model directive works though).


More updates.

Looks like a no-op HostFactory (one that extends MvcRazorHostFactory but doesn't override any methods or contain any other code) works fine if you strong name it and install it in the GAC. I believe I was using the wrong GAC when testing that earlier, but (with some outside prodding) was able to get it working using the explicitly x64 gacutil.

Now the trouble is figuring out what's wrong with my particular host factory; more details coming as they're discovered.

like image 856
Kevin Montrose Avatar asked Sep 12 '12 00:09

Kevin Montrose


1 Answers

After some discussion with Microsoft, we found the root cause of this problem.

As usual, it was my code.

The root error was an MVC3 reference in the custom factoryType, despite the project (and everything around it) being MVC4.

To sum everything up, to get Visual Studio IntelliSense working in .cshtml files with a custom <host factoryType>:

  • You must strong name your assembly
  • You must install the assembly in the GAC
    • We still debug and deploy against a local copy, but VS will look in the GAC
  • You must have all the right references*

Be aware that you'll need to restart Visual Studio after installing into the GAC, simply reloading the solution is not (usually) sufficient. We've also found that some (but not all) ReSharper installations will need their cache's cleared, to be on the safe side clear the cache.

One minor trip up when adding a reference to an assembly that resides in the GAC is the Visual Studio won't copy it to your output directory by default, this may work for you but caused problems for us. You can change this in the properties of the reference.

enter image description here

Also, Visual Studio will give you a number error messages (the "Other Error" purple underline I was unable to reliably reproduce earlier) if your custom factory throws any exceptions; except perhaps in it's constructor (that seemed a little inconsistent).

Where you get no help is the case we were in, where the type itself has serious issues. It was just a coincidence that things worked at runtime (the interfaces we're playing with didn't change between MVC3 and MVC4, and weak naming did the rest).

*If you're like us and have MVC beta 1 through 4 installed, be aware of the PEBKAC in this step.

like image 71
Kevin Montrose Avatar answered Sep 29 '22 13:09

Kevin Montrose