Let me offer you another approach will let you know if you are in Azure, Azure Emulator, IIS or locally running integration tests. This is important because it is useful and faster to debug in IIS express the pure web projects that you will eventually run in Azure or run integration tests which may run even outside of IIS. Which means that you can debug your project faster and not waste all the time loading/running the azure compute emulator every time.
There are several ways to check this and that but here is another method that can help you move around in all the cases for a good ALM and development.
You have four available mechanisms to use :
- HostingEnvironment object in IIS
- RoleEnvironment object in Azure or Azure Emulator
- System.Environment object that you have everywhere.
- Configuration - In my case web.config, web.debug.config, web.release.config, web.debug.staging.config, web.release.production.config, app.config, ServiceConfiguration.Local.cscfg, ServiceConfiguration.CloudStaging.cscfg and ServiceConfiguration.CloudProduction.cscfg
The problem consists in that : If you try to access RoleEnvironment.IsAvailable or RoleEnvironment.IsEmulated in IIS without running in Emulator or in Azure - you will get an exception. In Azure Emulator with IIS will get an exception too if the environment is not yet ready - Emulator and IIS are running together and IIS is not waiting for the emulator even though you get through RoleEntryPoint before you get to Global.asax.cs. This 'thing' eliminates the possibility to wait like that
while(!RoleEnvironment.IsAvailable)
and resolve the issue quick and clean. This issue also eliminates the use of RoleEnvironment.IsEmulated because it will throw exception in local IIS or local integration test and it is not possible to check for RoleEnvironment.IsAvailable before it because if you wait for it to be ready outside of Azure or Azure Emulator you will wait for something that is going to be there.
Side note : Sometimes in the emulator environment can load later then your MVC project and accessing RoleEnvironment properties throws exception. This can be mitigated easily by waiting for it by calling
while(!RoleEnvironment.IsAvailable)
End of side note.
Side note 2
Setting Environment variable in RoleEntryPoint like that :
public class WebRole : RoleEntryPoint
{
public override bool OnStart()
{
Environment.SetEnvironmentVariable("CodeRunsInAzure","true");
}
}
will not work because they run in different places and you are not able to retrieve it like that :
Environment.GetEnvironmentVariable("CodeRunsInAzure")
in Global.asax.cs or elsewhere in your Web/Worker project. Otherwise the problem will be easily resolved.
End of side note 2.
The solution is in two parts. The first is in your configuration files. Just set the variable in your all your configs in which it is needed - *.cscfgs :
<Setting name="RunsInAzureCloudEnv" value="true/false"/>
in ServiceConfiguration.Local.cscfg - false and everywhere else in cscfg - true. Then in web.*.config / app.config accordingly
<add key="RunsInAzureCloudEnv" value="true/false"/>
This way the variable will be set to true only while you publish or you run it in the emulator otherwise it will be false.
One case of using this is when you want to run code only in azure - like updating the Edition of your old databases from the retired WEB edition to BASIC inside your custom implementation of IDatabaseInitializer. In this case you need to run your code only in Azure and only if it is not in the emulator but in your staging or production environment. The example usage is as follows :
// check the variable that is set only in azure environment
var runsInAzureEnvStr = CloudConfigurationManager.GetSetting("RunsInAzureCloudEnv");
bool runsInAzureEnv = false;
Boolean.TryParse(runsInAzureEnvStr, out runsInAzureEnv);
if(!runsInAzureEnv)
{
return;
}
If only the Emulator was ready before the MVC was launched only :
if(RoleEnvironment.IsAvailable && !RoleEnvironment.IsEmulated)
would be enough.
If somebody knows how to make the two happen in exact sequence and share it - it will be nice.