WebAPI in Service Fabric – DEVELOPPARADISE
08/05/2018

WebAPI in Service Fabric

Introduction

A good start to learn about Service Fabric is here.

Background

This article builds on this article where you find the original CarClient and CarAPI projects which in this article are moved to a Service Fabric Cluster.

Using the Code

Please note that this code is only tested on Google Chrome. The JavaScript in the client runs perfectly on Google Chorme but I have noticed problems with Internet Explorer and FireFox.

To run this sample, you need an Azure Account and your own Azure SQL Server app. You must update the connection string to point to your own Azure SQL Server. You also need Service Fabric Explorer and Service Fabric Cluster Manager which you get when you install the service fabric SDK.

SQLite has been replaced with Azure SQL Server and the CarClient and CarAPI projects are now stateless service fabric services.

To create this solution by Visual Studio, a Service Fabric Application has been chosen as solution template.

WebAPI in Service Fabric

In the solution, two stateless ASP.NET Core projects have been added: One WebAPI and one Web Application as shown below:

WebAPI in Service Fabric

The code from the older CarAPI and CarClient have been added to the default projects with as few modifications as possible. The solution can be run in both an Azure cluster and a local cluster. The Azure cluster is created by Visual Studio. When creating a SF cluster from Visual Studio, you get a cluster using certificate security. This forces the application to use https for the reverse proxy in Azure as opposed to running it locally where http must be used.

In Azure, the URL used for CarAPI is http://carfabric.northeurope.cloudapp.azure.com:83/ and in the local cluster, the URL http://localhost:83/ is used. This URL is used by JavaScript in CarClient for retrieving and updating data in the database. CarAPI can be checked with http://carfabric.northeurope.cloudapp.azure.com:83/swagger.

For CarClient, the same URLs are used except the port number is changed to 80. The URL is passed via the environment variable ApiAddressConnectionString which is defined in the ServiceManifest.xml for CarClient. How the value is defined when running the app locally respectively in Azure can be seen in Cloud.xml and Local1.xml in folder ApplicationParameters. The code for getting the reverse proxy address is as follows:

/// <summary> /// Constructs a reverse proxy URL for a given service /// Example: http://localhost:19081/CarFabric/CarAPI/ /// </summary> ///<param name="serviceName"></param> /// <returns></returns> public static Uri GetProxyAddress(Uri serviceName) {     string ApiAddress = Environment.GetEnvironmentVariable("ApiAddressConnectionString");     if (ApiAddress.IndexOf("localhost") > 0)     {         return new Uri($"http://localhost:19081{serviceName.AbsolutePath}/");     }     else     {         return new Uri($"https://localhost:19081{serviceName.AbsolutePath}/");     } } 

This code is found in project CarClient, file Utils.cs.

Comparing the HTTP Client code between the old traditional solution and the service fabric solution shows the differences clearly.

New Service Fabric code:

namespace CarClient {     public static class Utils     {         public static async Task<T> Get<T>(string url)         {             Uri serviceName = CarClientApp.GetCarAPIServiceName();             Uri proxyAddress = GetProxyAddress(serviceName);             HttpClientHandler handler = new HttpClientHandler()             {                 ServerCertificateCustomValidationCallback =                        HttpClientHandler.DangerousAcceptAnyServerCertificateValidator             };             using (var client = new HttpClient(handler) { BaseAddress = proxyAddress })             {                 client.DefaultRequestHeaders.Accept.Clear();                 client.DefaultRequestHeaders.Accept.Add                          (new MediaTypeWithQualityHeaderValue("application/json"));                 var response = await client.GetAsync(url);                 var content = await response.Content.ReadAsStringAsync();                 return await Task.Run(() => JsonConvert.DeserializeObject<T>(content));             }         }

The old code is as follows:

namespace CarClient {     public static class Utils     {         priavte static readonly Uri Endpoint = new Uri("http://localhost:54411//");         public static async Task<T> Get<T>(string url)         {              using (var client = new HttpClient() { BaseAddress = EndPoint })             {                 client.DefaultRequestHeaders.Accept.Clear();                 client.DefaultRequestHeaders.Accept.Add                             (new MediaTypeWithQualityHeaderValue("application/json"));                 var response = await client.GetAsync(url);                 var content = await response.Content.ReadAsStringAsync();                 return await Task.Run(() => JsonConvert.DeserializeObject<T>(content));             }         }

For implementation details, please download CarFabric.zip and read the code. You can also run the sample on http://carfabric.northeurope.cloudapp.azure.com.

Points of Interest

When creating a SF cluster from Visual Studio, you get a cluster using certificate security. This forces the application to use https for the reverse proxy in Azure as opposed to running it locally where http must be used.

History

  • 8th May, 2018: Initial version