Similar to the web service, we add Application Insights to the website, pointing it to the dev instance of Application Insights in Visual Studio. This adds an instrumentation key to the appsettings.json file. We also setup some app settings to track the environment, (we name this one “VS dev”, but will update it in Azure DevOps to track deployments to our dev, qa and prod environments), the web service URL, and the location of the images in the Azure storage container.
Adding Polly to our website controller to make our API calls more resilient
To call our web service from our website, we are going to use “Polly”, as it contains some useful functions to make our calls more resilient. To start using Polly, we add a new NuGet package, “Microsoft.Extensions.Http.Polly”. In our StartUp.cs file, we add a policy to retry a failed async call 3 times. We also add a “Scoped” setup on line 42 to use the “ServiceAPIClient” class we will write next – this will contain the logic to call the web service. With these lines in the StartUp.cs, this resiliency rule is now globally available to all of our service calls! If there is an outage or bad network connection, Polly will automatically retry up to three times before failing the request.
Next we create and “IServiceAPIClient.cs” interface, defining methods we will need in the class.
Then we add code to the actual “ServiceAPIClient.cs” class to call the web service, using the “Polly” code we added to the “StartUp.cs” code earlier. This is using dependency injection to build the resiliency, as well as defining the services calls required to get the data from the API. You’ll also notice two private helper functions starting on line 43 we defined to minimize repeated code.
In the controller, we use dependency injection again to bring in the service API client. As we are returning a few items back to the view, we create a simple “IndexViewModel”, with two properties, to help organize our data on the view.
Resolving JSON reference loop and truncation issue
As we were starting to write unit and integration tests for this code, we kept receiving an error in our integration tests about JSON reference loop errors. Browsing to the API call directly, we can also see that the JSON is being truncated.
After some research, it seems to be related to our table structure in EF Core that has foreign key references in multiple directions, which is causing a circular loop in EF. We can resolve it today by adding some code to our StartUp.cs file to ignore these errors. We are comfortable ignoring these errors because we understand the data structure and know we won’t be using the data in away that would populate it in a loop.
With this change, the output now displays the complete result, problem solved!
Adding Razor code to render our web pages
Next we start to setup the Razor code in our HTML. At the top of the page we reference the model we are returning, and then in the HTML we create simple table headers (lines 9 to 17), loop through the “OwnerSets” property of the “IndexViewModel” (line 18), and then we loop over this data from our to populate our content (lines 22 to 31).
We load our website and can see our pages rendering the data – in our migration process, we imported in images of the parts into folders sorted by part color. The index looks great, but as we start to setup our set details pages.. the lack of styling is very noticeable. We haven’t customized any CSS yet, which is really evident with the images coming in as all different, but really large sizes.
We start build some styles in our CSS to maximize the size of an image. As we load these images, we quickly realize that we are also missing some images.
Now a default image displays when the image can’t be found. Unfortunately this does still display an error in the console, “Failed to load resource: the server responded with a status of 404 The specified blob does not exist.”, so we do still need to look at the data.
Setting up static files with bundling and minification
First, we add the “BuildBundlerMinifier” NuGet package to the website project and then a “bundleconfig.json” file to the root of the web project. In the bundleconfig.json file, we add the text below, to minify the site.css and site.js files to site.min.css and site.min.js files. With this, when we release our application, it will shrink our files, reducing their size and optimizing their performance – but our development environment keeps the files readable and easy to debug.
Finally, we add add a favicon,ico file to our wwwroot folder, as well as a line 8 in the _Layout.cshtml to reference it.
As well as not displaying an error in the console, this now shows our cool little icon in the browser tab! This will also show if a user creates a bookmark/favorite to our website.
Privacy, GDPR and cookies
- Adding resilience to HttpClient with Polly:
- Resilient applications: https://docs.microsoft.com/en-us/dotnet/standard/microservices-architecture/implement-resilient-applications/use-httpclientfactory-to-implement-resilient-http-requests
- Bundling: https://docs.microsoft.com/en-us/aspnet/core/client-side/bundling-and-minification?view=aspnetcore-2.2&tabs=visual-studio
- Featured image credit: https://organicthemes.com/wp-content/uploads/2013/10/website-construction.jpg