Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect when Visual Studio is test-firing the website for intellisense

There's a lot of exposition here - but it's needed.

Not sure how many people are aware of this, but, the Razor code editor in Visual Studio causes your website to be 'test-fired' up to just before the Application_Start event - and this is causing some annoying issues in my current project, which uses WebActivator to do a lot of the site initialisation.

Update - On closer inspection it's not just Razor - it looks like it's Visual Studio-wide - hence the change of title

I need to be able to detect when website code is being run by Visual Studio and not by a web server.

To demonstrate - do the following (exactly as written to ensure it reproduces):

  • Create a new MVC 4 site, I used the Internet Application template so there were some pages there on creation.
  • Add the WebActivator package from nuget
  • Add a class to the App_Start folder called RazorPageBugTest
  • Paste this code (changing the relevant namespace):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MvcApplication6.App_Start;
using System.IO;

[assembly: WebActivator.PreApplicationStartMethod(
  typeof(RazorPageBugTest), "Start", Order = 0)]

namespace MvcApplication6.App_Start
{
  public static class RazorPageBugTest
  {
    public static void Start()
    {
      using (var writer = File.Open(@"c:\trace.txt", FileMode.Create))
      {
        using (var tw = new StreamWriter(writer))
        {
          tw.AutoFlush = true;
          tw.WriteLine("Written at {0}", DateTime.Now);
        }
      }
    }
  }
}

Notice that this code is not something that would usually work on a web server anyway - given that it's writing to drive C: (indeed this might not work on your machine if you don't run VS as administrator).

  • Now build the project.
  • This next bit works best if you already have Explorer open on C: Once that's completed, find a Razor view and open it
  • Wait for all the C#/VB bits to be highlighted
  • Take a look at drive C - oh look, there's a file called 'trace.txt' and the date is within the last few seconds!

So that demonstrates the problem here - the Razor code editor is firing up an AppDomain and, effectively, shelling the website in order to get intellisense (including things like stuff in the App_Helpers folder etc). Now it doesn't actually trigger the Application_Start method - but when you have WebActivator in the project as well, any of its pre-application-start methods are triggered.

In my case this is causing huge issues - high CPU usage and memory usage in devenv.exe (equivalent to the website having just been started) because I initialise DI containers and god-knows what else at this point, but one in particular is proving really annoying.

My website has a component that listens on the network for status and cache-invalidation messages from other machines in the web farm. In QA and Live environments this listener never fails to open the port and listen - on my dev machine, however, it frequently fails - saying the port's already in use. When I look for the process that's holding it open - it's always devenv.exe.

You guessed it - I start this listener in a WebActivator-initialised boot-strapping call.

So the question is - does anyone know of a way to detect that the code isn't being run by a 'proper' web host so I can stop it being run? I'm particularly hopeful for this as it'll also mean that my Visual Studio and Razor editing experience will become a damn-site faster as a result!

As a bonus, any fix could legitimately be sent to David Ebbo - author of WebActivator - so he can stick it earlier in his stack to prevent the problem completely!

Update

I have just added an issue to the WebActivator page on GitHub to see if David Ebbo can push either my fix, or a better one, down into the WebActivator component.

like image 770
Andras Zoltan Avatar asked Oct 12 '12 12:10

Andras Zoltan


Video Answer


1 Answers

Guess what the value of Process.GetCurrentProcess().ProcessName will be in this case?

Answer: Microsoft.VisualStudio.Web.Host.

So if there's a VisualStudio in the name of the process, you could safely scrape it.

Also check this article out about the hosting process.

like image 85
Darin Dimitrov Avatar answered Sep 28 '22 01:09

Darin Dimitrov