Part 3: Build containerized web dashboard with ASP.NET Core

June 16, 2018 by rdagumampan

This is part of a five-part series in my exploration of Azure microservices facilities.

  1. Kick-start containerized microservice CI/CD with Azure DevOps
  2. Build containerized microservices with Docker and .NET Core 2.1
  3. Build containerized web dashboard with ASP.NET Core
  4. Email service health report with Azure serverless
  5. Scale out services with Managed Kubernetes

Creating the service health dashboard

We’ll KISS it. The front end layer displays the state of services and the heartbeats we received. It also shows last known location of the service because microservices move around the infrastructure a lot. The video (with my wife’s voice offering juice!) is a teaser.

  1. Create view models

    public class SolutionVm
    {
        public string Name { get; set; }
        public List<ServiceHealthDto> Data { get; set; } = new List<ServiceHealthDto>();
    }
    
    public class ServiceHealthVm
    {
        public string ServiceId { get; set; }
        public string ServiceName { get; set; }
        public string Description { get; set; }
        public DateTime LastPing { get; set; }
        public string LastLocation { get; set; }
        public double AliveSince { get; set; }
        public string LastStatus { get; set; }
    }
    
  2. Create view

    @using Newtonsoft.Json
    @model SolutionVm
    <h3>You are viewing @Model.Name workspace</h3>
    <h4></h4>
    
    <br />
    <table class="table table-sm table-hover table-bordered" >
        <thead class="thead-dark">
            <tr>
                <th>ServiceName</th>
                <th>LastKnownLocation</th>
                <th>LastHearbeatUtc</th>
                <th>LastStatus</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var d in Model.Data.OrderBy(s=> s.LastPing))
            {
            <tr>
                <td>@d.ServiceName</td>
                <td>@d.Location</td>
                <td>@d.LastPing</td>
                <td class="@(d.AliveSince < 600 ? "bg-success":"bg-danger")">
                    @(d.AliveSince < 300 ? $"Running" : "Last heartbeat "+ d.AliveSince.ToString("#") +" secs ago, verify ASAP")
                </td>
            </tr>
            }
    
        </tbody>
    </table>
    
  3. Create the view controller

    //view controllers
    public class HomeController : Controller
    {
        public IActionResult Index()
        {
            var serviceClient = new ServiceHealthClientService();
            var servicesHeatlth = serviceClient.GetDataAsync();
    
            var solution = new SolutionVm
            {
                Name = "Services",
                Data = servicesHeatlth.Result
            };
    
            return View(solution);
        }
    }
    
  4. Create service facade

    This assumes you have the service-api container running locally and mapped into port 8080.

    public class ServiceHealthClientService: IServiceHealthClientService
        {
            public ServiceHealthClientService()
            {
            }
    
            public async Task<List<ServiceHealthDto>> GetDataAsync()
            {
                var results = new List<ServiceHealthDto>();
    
                string baseUrl = "https://localhost:8080/api/servicehealth";
                using (HttpClient client = new HttpClient())
                using (HttpResponseMessage response = await client.GetAsync(baseUrl))
                using (HttpContent content = response.Content)
                {
                    string data = await content.ReadAsStringAsync();
                    if (data != null)
                    {
                        results = JsonConvert.DeserializeObject<List<ServiceHealthDto>>(data);
                    }
                }
    
                return results.OrderBy(s=> s.ServiceName).ToList();
            }
    
        }
    
  5. Dockerize it

    FROM microsoft/aspnetcore-build:1.1 AS build-env
    WORKDIR /app
    
    # Copy csproj and restore as distinct layers
    COPY *.csproj ./
    RUN dotnet restore
    
    # Copy everything else and build
    COPY . ./
    RUN dotnet publish -c Release -o out
    
    # Build runtime image
    FROM microsoft/aspnetcore:1.1
    WORKDIR /app
    COPY --from=build-env /app/out .
    ENTRYPOINT ["dotnet", "aspnet-core-dotnet-core.dll"]
    
    / docker build . -t servicehealth-web
    / docker images
    
  6. Test it

    / docker run -d -p 8010:80 -name servicehealth-web servicehealth-web
    / docker ps
    

    You can pre-load the database table ServiceHealth just to see how its layout. The default address is http://localhost:8010, try on browser.

    ServiceHealth

© 2017 | About | Contact | Follow me on Twitter | Powerered by Hucore & Hugo