Developing ASP.NET web services on Service Fabric has come a long way: ASP.NET Core's self-hosting web host model fits right in with Service Fabric's hosting model, and the new ASP.NET Core NuGet packages for Reliable Services make it easier than ever to get up and running. But when it comes to rapidly developing web apps, you've probably noticed it's not all that rapid. In fact, it can be downright slow, because every time you make even the smallest CSS change, you have to wait for the whole application to redeploy to actually see your changes in a browser. Setting up a compiler flag to go back and forth between actual deployments and just running in-place to avoid the wait is commonplace, along with banging your head against the keyboard if you're anything like me.
To get us back to the rapid application development we've become accustomed to, we've added a new application debug mode called "Refresh Application" - currently in preview - to the Visual Studio tools for Service Fabric in the 2.5 release of the Service Fabric SDK. This new mode lets you make changes to your service projects and see the updates live without having to redeploy or upgrade the entire application. You can enable it by selecting Refresh Application (Preview) for Application Debug Mode in your application properties (right click your application project and select properties).
Let's take a look at why this is so awesome, starting with some background info.
Most app development is a rapid back-and-forth flow of change something, then see the results. For ASP.NET Core development, that flow is especially important where you change a (cs)html, css, js, or whatever file in Visual Studio and refresh your browser to see the changes. When you need to make a change to some C# code, you recompile and again refresh the browser or resend a request to see the change in action. This has always worked smoothly because the web server has its wwwroot pointing directly to your development directory, which you have open right there in Visual Studio.
But Service Fabric is different. Service Fabric isn't a simple web server or single EXE - it's a complete distributed application platform. When you deploy an application to Service Fabric, web server and all, the application is packaged up and placed on a specific node - or set of nodes - in a cluster of virtual or physical machines where it will run. In a normal multi-node environment, this means your application package is being distributed across a set of virtual or physical machines. A local development environment is no different except all the nodes happen to be hosted on the same machine - remember, there is no emulator. Either way, when the application is running, it's no longer in your development directory. Service Fabric uses a special directory structure on each machine to organize all the different versions and instances of your applications and services.
For example, on my dev machine I'm developing our Getting Started application sample in this directory:
But when I run that application, it's being packaged up and deployed to a Service Fabric cluster where the package is placed in a "deployment" directory. On a local development cluster with the default setup, that directory looks something like this:
And there's the problem. I make a change to a file in the development directory, but I won't see a change in the live running application because it's being run from the Service Fabric application deployment directory, and it can take a while to do the whole dance of recompiling, packaging, uploading, registering, and creating or upgrading the application, especially for large web applications.
Enter Refresh Application debug mode to save the day (or at least save a lot of time). Refresh Application debug mode instructs the Service Fabric hosting layer to do something a little different during deployment. Instead of copying the application package down to the usual Service Fabric application deployment directory, it instead creates symbolic links back to the development directory. We had to make a few changes in the Service Fabric hosting layer to make this possible. For example, you'll notice Visual Studio injects an ApplicationParameter to your application during deployment called _WFDebugParams_ that has directory mapping information, and when you look in the application deployment directory, you'll see a bunch of linked directories pointing back to your development directory:
Simple, but very effective. Now whatever changes you make in your development directory suddenly appear in the application deployment directory, so you can see your changes live as you make them.
There are of course some limitation to this new mode:
- It only works on a one node development cluster.
- It only supports changes to the contents of code, config, or data packages and the project directory contents in the case of ASP.NET Core projects. Application structural changes - like changes to ServiceManifest.xml or ApplicationManifest.xml - aren't supported because the structure of the deployed application may change with unwanted results. You can still make structural changes while in Refresh Application debug mode, but if you do, the application will be redeployed.
- Stateful services don't maintain their state if you recompile. In order to get your new binaries running, the service has to be removed to stop the process so new binaries can be written to disk, which of course means all your state is wiped out. This is usually fine for rapid development, but to really test your stateful services you'll still need to run them in a 5-node cluster.
You can probably tell from these limitations that this mode really is for that stage of development where you're making lots of changes and want to see the results quickly. But once your application development has stabilized, it's a good idea to switch over to Auto Upgrade Application Debug Mode on a five-node local cluster, so that your changes are then deployed to a multi-node environment via actual rolling upgrades. It's important to get used to rolling upgrades even while you're still on a local cluster, because that's exactly what you'll be doing in production later on, and you don't want to wait to practice your first rolling upgrade once you're in production.
So give this new mode a try and let us know what you think. It's available now as a preview feature in the 2.5 release of the SDK.