Run a Service Fabric solution locally without deploying to Service Fabric

This is a similar piece to another post of mine from a few years ago Run a Windows Azure cloud service locally without the Azure compute emulator

So you’re working on a Service Fabric application which has an ASP.NET Web api host project. I find the debugging experience painful, for two reasons:

  1. Time to start debugging the project is a minimum of 45 seconds, every time, because the app gets deployed to a local service fabric cluster which takes forever.
  2. You need to remember to run Visual Studio as administrator in order for the above local deployment to succeed.

If either of these things bug you, then here’s a possible solution. Once we’re done you’ll be able to set the Web project in your solution as the StartUp project instead of the Service Fabric application, for much faster debugging, and you’ll no longer need to run VS as admin.

First, change the Program.cs in the Web project:

private static void Main()
{
	if (UseServiceFabric())
	{
		StartServiceFabric();
	}
	else
	{
		StartWebHost();
	}
}

private static bool UseServiceFabric()
{
	var webHostBuilder = new WebHostBuilder();
	var environment = webHostBuilder.GetSetting("environment");

	return environment != "Development";
}

private static void StartWebHost()
{
	var builder = new WebHostBuilder()
		.UseKestrel()
		.UseContentRoot(Directory.GetCurrentDirectory())
		.UseStartup<Startup>();

	var host = builder.Build();
	host.Run();
}

private static void StartServiceFabric()
{
	try
	{
		// The ServiceManifest.XML file defines one or more service type names.
		// Registering a service maps a service type name to a .NET type.
		// When Service Fabric creates an instance of this service type,
		// an instance of the class is created in this host process.

		ServiceRuntime.RegisterServiceAsync("Web1Type",
			context => new WebHost(context)).GetAwaiter().GetResult();

		ServiceEventSource.Current.ServiceTypeRegistered(Process.GetCurrentProcess().Id, typeof(Web1).Name);

		// Prevents this host process from terminating so services keeps running. 
		Thread.Sleep(Timeout.Infinite);
	}
	catch (Exception e)
	{
		ServiceEventSource.Current.ServiceHostInitializationFailed(e.ToString());
		throw;
	}
}

If the ASPNETCORE_ENVIRONMENT setting is Development, then it won’t use Service Fabric at all and will just use a plain ol’ ASP.NET Core WebHostBuilder to start the web host.

You’ll also need to change your Debug target to be the Web project, instead of IISExpress, via the VS Standard toolbar.

And just like that the app startup time has shrunk from around 40 seconds to around 5 seconds. Or from an unbearable 100 seconds for the application the team I just joined is working on.

Advertisement

Azure Emulator not working with SQL server alias

I just spent a few hours trying to figure out something that had me stumped.

In my local dev environment I’m building a web api which has a SQL database. The connection string for the database is an alias with a named pipe. If I set the web api as StartUp project in Visual Studio it works fine. (See this post for some tips on how to do that). But when I’d instead start the Azure emulator as the StartUp project it wouldn’t connect to the sql server, with the good ol’:

A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)

Eventually I figured it out. The alias was the problem, because if I changed the connectionstring to .\sqlexpress it worked fine.

Digging deeper, the problem was I had set up the alias on the “SQL Native Client 11.0 Configuration (32bit)” node, but I hadn’t added an alias on the “SQL Native Client 11.0 Configuration” node. So the fix was to create an additional Alias on the “SQL Native Client 11.0 Configuration” node.

sql

So it seems that debugging a web api locally may be a 32 bit process but debugging with the Azure emulator is a 64 bit process. Maybe?

Anyway, hope this helps someone.

Run a Windows Azure cloud service locally without the Azure compute emulator

A big bugbear when developing Azure cloud services is the Azure emulator. You make a code change and the write – compile – debug process is slowed down big time because you have to wait for the Azure emulator to start up every time.

One project I worked on had a Web API running in an Azure cloud service and an ASP.NET MVC website running in another cloud service. So in order to develop it locally we had to run 2 instances of Visual Studio 2013 and each of them would fire up an emulator. Needless to say this was quite the resource hog and we’d every now and then see unexpected issues with Visual Studio or the emulators. Oh and the emulators would fight over which ports they would run on so we had to ensure we started debugging the API first so that it would get port 443 and then start the website which would default to 445.

So why can’t we just install our Web API and ASP.NET MVC website into IIS and not use the emulators? Well there are two blockers:

  1. The Azure diagnostics config will throw exceptions if we’re not running in Azure
  2. Settings are read from cloud config values in ServiceConfiguration.cscfg via RoleEnvironment.GetConfigurationSettingValue which needs Azure

My colleague Dylan came up with a solution. Basically, in the Global.asax.cs of both our website and our web api, we need to check if we’re running in Azure or not.

If we are in Azure, then use 1. configure Azure diagnostics config, and 2. read cloud config values using the default RoleEnvironment.GetConfigurationSettingValue.

If we are not in Azure, then 1. don’t configure Azure diagnostics, and 2. read cloud config values from ServiceConfiguration.cscfg manually via XML. parsing.


if (RoleEnvironment.IsAvailable) // we are in Azure
{
    Trace.Listeners.Add(new DiagnosticMonitorTraceListener());
    Trace.AutoFlush = true;
}
else
{
    var di = new DirectoryInfo(HttpContext.Current.Server.MapPath("~"));
    var solutionRoot = di.Parent;

    var xdoc = XDocument.Load(solutionRoot.FullName + @"\Identity.Web.Azure\ServiceConfiguration.cscfg");
    ConfigurationSettingsProvider.Current = new NotInRoleEnvirovmentConfigurationProvider(xdoc, "Identity.Web");
}

Our ConfigurationSettingsProvider.Current is by default a DefaultConfigurationSettingsProvider which uses RoleEnvironment.GetConfigurationSettingValue(key) to read the cloud config – we use one of these when we’re in Azure.

Our NotInRoleEnvirovmentConfigurationProvider reads the .cscfg file using XDocument.

So now I can install our website and web api into IIS locally – and code changes are visible after a compile. No need to run 2 Visual Studios and wait for the memory hungry emulator to startup every time. If I need to debug I can Debug -> Attach to process. Much more productive :-)

Browse and debug an Azure web role website running locally on a mobile device

So, you’re developing an Azure website using a Web role, and now you want to see what that website looks like on a mobile device.

First, follow my instructions here to set up port forwarding for your website.

Once you’ve done that, assuming your mobile device is on the same network as your PC running the Azure web role, you should just be able to open the URL for the website in your mobile web browser – in my case this https://10.200.34.201:800/

If you need to debug the traffic between your Azure web role and the mobile device, you can do that using Fiddler or Charles proxy. Fiddler instructions here. Charles instructions here. And SSL instructions for Charles here, if your site runs on SSL.

If you need to manipulate the traffic between Azure and the mobile browser, you can use Fiddler’s custom rules to do that – in my case I had to inject a “IsMobile=true” header. Fiddler -> Rules -> Customize Rules. Locate “static function OnBeforeRequest” and add the following line to it. oSession.oRequest[“IsMobile”] = “true”;

Browse a local Azure Web role from another computer

So, you’re developing an Azure website that runs as a web role, which means you use the Azure Compute Emulator when running it locally. And now you want to test or debug that local website in an older browser, such as IE8.

In this situation I have IE8 running on another computer (or maybe a VM), so I need to open up access to my website which is running locally.

Step 1. Find out your IP address – ipconfig. Mine is 10.200.34.201 (NB. I’ve highlighted the wrong field in the screenshot).
image002

Step 2. Find out which IP address and port the compute emulator is running on, by looking in the System Tray at the IIS Express icon. Note that even though I access the website locally on https://127.0.0.2:447 in my browser, it runs on a different IP and port in the emulator, https://127.255.0.4:448. I don’t know/care why.
image001

Step 3. Download and install Pass Port from http://sourceforge.net/projects/pjs-passport/. Yes it’s old but it does the job of forwarding ports nicely, which is what we need to do.

Step 4. Set up a Pass Port port forwarding rule with your IP address and any port (I’m using 800) to the IP address and port of the emulator. N.B. you may need to run PassPort as an Administrator if it doesn’t seem to be working.

image004Step 5. Open up that port (800) in the Windows Firewall:

image003

That should be it. Now you can connect on the remote computer to your Azure Emulator running locally. Obligatory screenshot of my site running in IE8:

image005