Putting the pieces together to create a basic website

Posted by

We are going to add functionality to our website to call our web service and populate the website with content from the Azure database, as well as link to the images stored in Azure Storage. We will use “Polly” to call our web service and Razor to render our web pages. While there are a number of really useful JavaScript frameworks out there, today we want to focus on DevOps and Azure, and will use Razor for the UI.

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.

We will investigate the data later, but to cover this scenario today, in the image src tag, we add an “onerror” attribute and some JavaScript to default to a filler image if the part image we are looking for can’t be found.

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

Now that we have CSS files, we want to run bundling and minification on them, performance optimizations that reduce the number of server requests and size of the requested static assets, such as CSS and JavaScript. We add some styles to our CSS. Unfortunately, minification is not automatically part of the ASP .NET 2.1 template for an MVC website. While the template has minified files, the middleware to support it is not automatically included. Fortunately it’s 3 quick steps to add the middleware:

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

As of ASP .NET Core 2.1, privacy warnings are already built into the templates. As our site (will) definitely use cookies, we make some minor edits to the text and link to the external website https://cookiesandyou.com/, which helps to explain what cookies do and why they are required on most websites in 2019. This looks great, and now our site is disclosing what we keep about it’s users.

Wrapup

Today we setup our website to communicate with the web service with Polly – with resiliency, fixed a JSON bug, bundled and minified our CSS and JavaScript, added a FavIcon to display our favorite icon, and created a banner to notify our users about cookies and privacy. The final result is view-able here: https://samsapp-prod-eu-web.azurewebsites.net/

References

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s