"Quick Find" Feature in the Productivity Power Tool Extension in Visual Studio 2010

   Submit to Reddit      
  

If you are like me, then you have installed a number of productivity related extensions for Visual Studio 2010, and sometimes it is difficult to know which extensions have each feature.

One feature that is in the Productivity Power Tools is Quick Find feature that replaces the default Find and Replace windows with the following.

I don't know about you, but I have a very healthy dislike for this feature - I am constantly clicking the dropdown box to select the Advanced Options to show the normal Visual Studio Find and Replace windows.

You can turn off this feature by going into Tools ➞ Options ➞ Productivity Power Tools in Visual Studio and turning off "Quick Find".

Note that after changing this option you will also have to restart Visual Studio for the change to take effect.

Intellisense in Razor for Custom Types and Helpers

   Submit to Reddit      
  

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:

<configuration>
    <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
            <probing privatePath="myBin" />
        </assemblyBinding>
    </runtime>
<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:

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

Minimal Configuration Required for Razor Intellisense in ASP.NET MVC 3 RTM

   Submit to Reddit      
  

Recently I have been creating some custom ASP.NET MVC 3 Helpers and have been working with some customised Visual Studio 2010 Web Projects (we effectively separate our Web Areas into individual Web Projects).

When working in these customised Web Projects for Web Areas, I have faced some issues with the Razor Intellisense. As it turns out, the issues were actually due to a lack of understanding of Razor's requirements for populating its Intellisense.

And so, here is the absolute minimal configuration needed to get Intellisense working properly in Razor for an ASP.NET MVC 3 Web Project.

(1) A Visual Studio Web Project (sorry, I have not tried Class Library Projects)

(2) A web.config file in the root of the project, with the following contents:

<?xml version="1.0"?>
<configuration>
  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
      <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      <add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      <add assembly="System.Web.WebPages, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
      </assemblies>
    </compilation>
  </system.web>
</configuration>

This is a cut-down version of the file that is created when you create a brand new, empty MVC 3 Web Project in Visual Studio.

Razor looks to this file in order to determine which assemblies from the GAC to load into its Intellisense. The assemblies listed above are the ASP.NET MVC 3 assemblies that contain the base class for a Razor view (System.Web.Mvc.WebViewPage) and the extension methods for all the standard MVC Helpers - such as HtmlHelper which is accessed through the @Html syntax, etc.).

If you had your own MVC Helpers that were strong named and deployed to the GAC, you could add them to the assemblies element.

All assemblies that are in the Web Project's private Bin folder are automatically loaded and made available in the Intellisense.

(3) A web.config file in the Views folder, with the following contents:

<?xml version="1.0"?>
<configuration>

  <configSections>
    <sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
      <section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" />
    </sectionGroup>
  </configSections>

  <system.web.webPages.razor>
    <host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
    <pages pageBaseType="System.Web.Mvc.WebViewPage">
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
      </namespaces>
    </pages>
  </system.web.webPages.razor>

  <system.web>
    <httpHandlers>
      <add path="*" verb="*" type="System.Web.HttpNotFoundHandler"/>
    </httpHandlers>

    <!--
        Enabling request validation in view pages would cause validation to occur
        after the input has already been processed by the controller. By default
        MVC performs request validation before a controller processes the input.
        To change this behavior apply the ValidateInputAttribute to a
        controller or action.
    -->
    <pages
        validateRequest="false"
        pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
        userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
      <controls>
        <add assembly="System.Web.Mvc, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" tagPrefix="mvc" />
      </controls>
    </pages>
  </system.web>

  <system.webServer>
    <validation validateIntegratedModeConfiguration="false" />

    <handlers>
      <remove name="BlockViewHandler"/>
      <add name="BlockViewHandler" path="*" verb="*" preCondition="integratedMode" type="System.Web.HttpNotFoundHandler" />
    </handlers>
  </system.webServer>

</configuration>

This is exactly the same file that is created when you create a brand new, empty MVC 3 Web Project in Visual Studio.

This web.config file importantly:

(a) Declares the default class that a Razor View/page inherits from (note: System.Web.Mvc.WebViewPage contains the Html and Ajax properties that are referenced by @Html and @Ajax respectively). The class that a specific Razor View inherits from can be overridden in the Razor syntax with the keyword @inherits.

(b) Declares the namespaces that are automatically imported - instead of having to use the @using Razor syntax. This is particularly important because it is the mechanism through which the MVC Helper extension methods are made available.

And that is all you need to get Razor Intellisense working!

Thread-Safe Lazy Singleton Implementation in .NET 4

   Submit to Reddit      
  

It has been a while since I needed to develop a singleton in .NET, and now that I am working in .NET 4 I thought it was a good time to revisit the implementation and take advantage of new language features.

So without much fanfare, here it is:

Public NotInheritable Class MySingleton

#Region " Thread-Safe Lazy Singleton "

    Private Shared _instance As Lazy(Of MySingleton) = New Lazy(Of MySingleton)(Function() New MySingleton())

    ''' <summary>
    ''' Hide the constructor
    ''' </summary>
    ''' <remarks></remarks>
    Private Sub New()
        ' nothing to do
    End Sub

    ''' <summary>
    ''' Singleton instance
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Shared ReadOnly Property Instance As MySingleton
        Get
            Return _instance.Value
        End Get
    End Property

#End Region

End Class

The .NET 4 Lazy class by default ensures that the singleton is thread-safe.

If you use the Lazy class and do not pass in any parameters, it will construct the type automatically for you... which means that the class must have a public constructor method with no parameters. By passing a value factory delegate into the constructor of the Lazy class, we can keep our constructor private and thereby force others to use our Instance property and truly make a Singleton.