Intellisense in Razor for Custom Types and Helpers

If you have custom types and custom ASP.NET MVC Helpers, and if you set your Visual Studio Web Project’s Build Output Path folder to something other than the default bin\ location, then you will be in for a little surprise - you will not see your custom types in the Razor Intellisense!

It appears that Razor’s Intellisense uses the assembly binding probing path of your Web Project’s root folder and the bin sub-folder.

If your Build Output Path is a sub-folder of your Web Project application base folder / root folder (although I don’t understand why you would bother) you could make a change to the web.config file and add a probing privatePath configuration such as:

1<configuration>
2    <runtime>
3        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
4            <probing privatePath="myBin" />
5        </assemblyBinding>
6    </runtime>
7<configuration>

However, in the more likely scenario that you have a common central location for all of your assemblies that is outside of your Web Project application base folder / root folder, then unfortunately by design (for security and side-by-side execution) there is no configuration setting in .NET that is going to help. You cannot load assemblies from outside of your application base folder (via configuration in .NET) - unless they are strong named and in the GAC.

In my scenario, the Build Output Path is outside of the Web Project’s root folder, so configuration is not an option, and my assemblies are not strong named, so the GAC is not an option.

One solution is to create a Visual Studio 2010 Extension or post-build script that copies all the assemblies from my custom Build Output Path into the local bin sub-folder. That would work, although it would also slow down my build times and frankly isn’t elegant.

A better solution is to take advantage of the fact that in my scenario the bin sub-folder does not actually exist in my Web Projects. I can make it exist in Windows 7 by creating a symbolic link named bin which points to my Build Output Path - and then magically Razor Intellisense works!

Note that when you create a symbolic link you need to have Administrator privileges.

The syntax to create the symbolic link is:

1mklink /d x:\MyWebProject\bin y:\MyCommonAssembly\Bin

Lessons In .NET - Assembly Binding Configuration

The Microsoft .NET Framework 2.0 SDK Configuration tool is a GUI for the C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config file.

However, I was working on a machine that didn’t have the SDK installed and I didn’t want to install it on that machine. I needed to redirect an assembly by adding an <assemblyBinding> element, so I looked up the specification of the element at http://msdn.microsoft.com/en-us/library/twy1dw1e.aspx and went directly to the machine.config file in a text editor tool.

Regarding the appliesTo attribute, the documentation says the following:

… If no appliesTo attribute is specified, the <assemblyBinding> element applies to all versions of the .NET Framework.

I wanted my binding to apply to all the versions of the .NET framework, and I thought I would specify that in the XML by specifying appliesTo="", as below.

1<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1" appliesTo="">
2    ...
3</assemblyBinding>

In all applications that I am familiar with - and even in ASP.NET - an attribute that has a value of the empty string behaves like the attribute has not been specified.

However, if you manually add an assembly binding section, do NOT specify appliesTo="", because that will actually prevent the assembly bindings applying to any .NET version at all!

Even after installing and using the tool to remove/fix the inner details of all assembly bindings, the actual <assemblyBinding> element was not removed and the manually added appliesTo="" remained - and this would cause future havoc.

Moral of the story: do NOT specify appliesTo="" in an <assemblyBinding> element!!