I recently participated in a small hackathon with some Microsoft ninjas where we were presented with the problem, How do you host a bot in Service Fabric? It seemed like an easy problem that had probably already been solved, but it wasn't as straightforward as we thought it might be.
At its core from a technology perspective, a bot is really just a Web API. We didn't want to actually host IIS on Service Fabric, so we knew we would want to self-host. If you use the built-in Stateless Service ASP.NET Core template, you'll get a great Web API implementation that's wired up with a KestrelCommunicationListener for Service Fabric. But what if you want to use Katana – Microsoft's .NET Framework OWIN implementation?
Katana is a flexible set of components for building and hosting OWIN-based web applications on .NET Framework.
Microsoft's Katana Project on GitHub
Although ASP.NET Core has incorporated most of the Katana project's functionality, the project will still be kept up-to-date and ensure any bugs are fixed per their roadmap. Most will look to ASP.NET Core for new functionality, but if you are maintaining a project built with a Katana dependency that you would like to port to be hosted in Service Fabric, you will only need to build a Katana-based ICommunicationListener implementation.
Note: this project was built and all screenshots were taken using Visual Studio 2017, version 15.5.2
Setting up the Service Fabric Application
We know we'd like to build a Stateless Service to host the Web API, so we'll first create the Service Fabric Application by using the File menu > New > Project... option. Find Service Fabric Application under the C# / Cloud templates.
After you've picked a name for your application, select Stateless Service as your first service in the application. If you select Stateless Service ASP.NET Core, it will automatically include the KestrelCommunicationListener and stub out an ASP.NET Core Controller; however, selecting the Stateless Service will create a service with only Service Fabric scaffolding and no default communication listeners.
At this point, we just need to create a Service Fabric ICommunicationListener for Katana, and we should be able to self-host any full framework ASP.NET website within Service Fabric.
Creating the OWIN ICommunicationListener
It turns out we definitely were not the first to have to implement an OWIN ICommunicationListener, but it is not something available in the Service Fabric libraries. This page of the documentation describes how to implement your own communication listener as required for Service Fabric reliable services communication stack. The Service Fabric team also has provided a sample available as part of the Azure Service Fabric Party Cluster sample. The PartyCluster.WebService uses an OwinCommunicationListener. There is also a somewhat-outdated example documented here that helps describe the implementation step-by-step. Because this example has not been kept up-to-date, there are a few method signatures that are no longer correct, but it might be worth a read to understand what is happening before using the OwinCommunicationListener from the Party Cluster sample.
Pulling this all together, our Stateless Service code now has four additional updates:
OwinCommunicationListenerclass: Sets up the Katana-based self-hosted web server and manages it within the Service Fabric Reliable Services communication stack
IOwinAppBuilderclass: Interface supporting OWIN configuration as part of the application builder stack during startup
Startupclass: Startup class to support configuration; passed into the
- Updates to
StatelessServiceimplementation: Registers the
You'll also need to configure the service to define the ports that will be used. For this example, we used port 80. This must be added to the configuration in the Service Manifest (found under the PackageRoot directory). Update the
ResourceEndpoints section so that it includes the following for this
<Endpoint Name="ServiceEndpoint" Protocol="http" Port="80" Type="Input" />
Adding the Bot
We decided to make one additional change in our implementation. We wanted to keep our Stateless Service as thin as possible, so we created a separate Web API project to contain our controllers, models, and some startup information versus adding these files directly within the Stateless Service project.
For this example, we just used the basic Echo Bot provided as part of the Microsoft Bot Framework's Bot Builder SDK. Their quickstart provides a great walkthrough as well as links to download the Visual Studio templates. Once the templates are installed on your machine, you just have to right-click the solution and add a new project. Search for and select Bot Application.
You now have an Echo Bot ready for use in your application. The final piece that ties these two projects together is the addition of configuration in the
Startup class we added to the Stateless Service project. It needs a reference to the Bot Application project so that you can make a call to
WebApiConfig.Register(config);. You'll also need to ensure
appBuilder.UseWebApi(config); is called since it will setup the Web API bits in the OWIN stack to ensure that is routed and handled correctly by your controllers.
Although the Katana implementation has been supplanted by a fully-featured ASP.NET Core stack, it may be helpful to support some legacy applications with Katana dependencies in Service Fabric. With these small changes, you can have a complete OWIN stack based on the full-framework Katana project implementation for use within Service Fabric. A complete working example is available on the CodingWithSasquatch GitHub site in the Zohan.ServiceFabricBot repository.