Telerik blogs
BlazorT4_1200x303

In this series, we’ll demonstrate how to create a client-side Blazor application with a Telerik UI for Blazor component. We’ll then show how we can integrate this application with a simple Serverless Function API from each of the “big three” cloud providers. This post features a comparison of the three.

Introduction

Hello and a very warm welcome to this five-part series where we’re going to:

  • Create a simple Blazor WebAssembly application paired with a Telerik UI For Blazor Chart component. (The Chart’s demo page shows a glimpse of what it looks like.)

    » The chart component will be used to display a dataset containing some arbitrary information.

  • Create three separate versions of a basic “HTTP-Triggered Serverless Function” using the “big three” cloud providers—Azure, AWS and Google Cloud.

    » Each cloud solution will be created using the equivalent “serverless function” service, coded using C# .NET, in a way to make them as similar as possible.
    » The reader can choose to go directly to the article applicable to the platform that they already use/prefer—or read all three to learn how the development experience compares.

  • Later in this article, we’ll also review and compare some aspects of the three cloud providers.

This series is not intended for the absolute beginner, but could suit existing .NET developers looking to learn a bit more about “serverless” solutions using straightforward examples.

Series Contents

If you’re planning to follow along with this series, you will need to create a Blazor client application, following the instructions in Part 2. Having completed that step, we’ll then look at creating a backend API.

If you already have a preferred cloud provider, you can go straight to the matching article.

If you’re interested to learn how the experience compares between the cloud providers, a succinct comparison is below, and you may further be interested in reading all three of the platform-specific articles in this series.

Blazor and Telerik UI Components for Blazor

“Blink … and you’ll miss the latest framework!” is a meme familiar to many developers … yet somehow Blazor has now been with us for about four years (at the time of writing)!

Briefly, ASP.NET Blazor first appeared in 2017 as an experiment by Microsoft’s Steve Sanderson and was adopted shortly thereafter by Microsoft’s ASP.NET team. Blazor was formally announced early in 2018.

Shortly after, Progress Telerik announced a suite of UI components that complemented Blazor. The first release of these components appeared early in 2019.

Blazor was fully released early in 2020, including full product support for both flavors of Blazor—Blazor WebAssembly (WASM) and Blazor Server.

With the release of .NET 6 in November 2021, we also received LTS (long-term support) for Blazor. Combined with a number of appealing improvements, such as reduced download size, this makes Blazor an increasingly appropriate choice for production and enterprise use—especially for teams already strong with .NET skills.

It’s a fast-evolving product, with interesting features emerging, such as Blazor ahead-of-time (AOT) compilation, which purports significant runtime performance gains.

Telerik Blazor evolves quickly too. Today, the current version is Telerik UI for Blazor 3.0, representing a matured selection of versatile and easy-to-use components that broadly fall into the following categories:

  • Data Management
  • Scheduling
  • Editors
  • Data Visualization
  • Interactivity & UX
  • Navigation
  • Layout
  • Document Processing
  • Gauges

Serverless Computing

A requirement often faced by developers, especially those more accustomed to frontend work, is:

"How can I create a simple backend API(s) to support my app, using a straightforward-to-use, managed cloud service?"

This is an example of where “serverless computing” is a great option.

Briefly, serverless computing is a way to host small pieces of event-driven code, usually with very little involvement in the underlying infrastructure. Typically, those computing resources are allocated on demand, which leads to usage efficiencies and scaling benefits.

In order to maintain commonality, each example of a serverless API in this blog series will address the following key focal points:

  • HTTP-triggered function – each solution will use the equivalent basic HTTP-triggered serverless function (rather than, for example, hosting an entire Web API app)
  • Command Line Interface (CLI) – the tutorials will demonstrate cloud setup and configuration using their respective CLI (rather than interacting using web portals)
  • Dependency injection (DI) – each solution will include at least a basic example of DI

image man looking at laptop in thought
Image credit: Andrea Piacquadio on Pexels

Comparing the Different Cloud Providers

While researching the individual articles in this series, I have been able to create side-by-side prototypes, using all three cloud providers.

I had initially intended to only present a series of how-to guides, but having the opportunity to work with all three platforms side-by-side—and having the editorial independence to comment without commercial bias—has presented an interesting opportunity to learn and form opinions.

Despite many similarities, there were some interesting differences between the developer experiences of these three cloud providers that you may be interested in reading about.

Note: If you are not interested in an objective opinion, and just want a “give me the facts tutorial”—it’s absolutely fine to skip over the rest of this particular article and dive straight into the other articles in this series!!! :-D

Let’s first acknowledge that different professional people/teams have very different needs, perspectives and skill sets. Whereas one group may absolutely love managed platforms, others may seek finer-grained control, or perhaps the flexibility offered by having many options.

It would be naive to attempt a generalized comparison—e.g., “Cloud X is better than Cloud Y.” A quick search will return dozens of such articles, which generally end up being nothing much more than subjective marketing spiel or feature listings that don’t really tell us much. As such, we’re not going to explore the breadth, reach, performance, reliability nor costs of the various cloud providers.

What Are We Comparing Then?

It would be more objective to focus upon the relative learning and development experience, as applicable to just that single “slice”—a simple HTTP-triggered serverless function—of the respective services.

More specifically, this would be from the perspective of a “relative newcomer, looking for a quick solution to a simple API requirement.”

I was particularly interested in:

  • How did I find the docs—specifically the quickstart?
  • What were the code samples like—e.g., were the templates useful?
  • What was the development experience like?
  • Any particularly noteworthy observations?

Azure Functions

azure logo

  • As would be expected, specific support for .NET in Azure Functions is strong—both in the supporting code samples and documentation.
  • Azure Functions natively supports .NET 6 directly on the host (if you are unclear what this means, we’ll be covering this subject in article 3 of this series).

Quickstart

  • Microsoft has done a good job with their quickstart experience. Using a single quickstart document, they managed to concisely convey both a C# language-specific example along with end-to-end CLI commands.

Sample Code

  • Microsoft supplies CLI templating, which includes a specific example of an “HTTP-triggered” function.
    • The sample includes sufficient code-stubbing to easily introduce the configuration needed for DI.

Developing/Debugging/Testing

  • An additional layer of locally installed tooling is required (the Azure Functions Core Tools), but otherwise, local development worked as usual and without compromise.

Other Observations

  • If you’ve only ever used Azure or GCF, it’s easy to not appreciate that Azure Functions automatically provisions HTTP endpoints. This happens both when developing locally and when deployed in the cloud.

    » I’m highlighting this because an endpoint is not an intrinsic part of Serverless Compute (even those that are intended to be HTTP triggered)—it’s conceptually a separate service. Granted, this endpoint won’t be named in a way that we would want to present directly to our customers (in which case, we would use another API Gateway service), but it’s perfect for internal service-to-service connections and testing. The fact that this is provisioned automatically cuts out needless process and friction.

  • I noticed a departure from the “managed platform ethos,” in that Azure requires us to provision and associate a separate storage account (into which deployed function code is published). This is something that neither Lambda nor GCF required us to do (at least, by default—acknowledging that both offer the option of using distinct storage), so seemed out of place for Azure.

Note: The process of creating a storage account is better streamlined if using alternative “Wizard” tools, such as those found in the Web Portal.

Read the full Azure post here.

Google Cloud Functions

google cloud logo

  • Google Cloud Functions offers strong specific support for .NET—both in the supporting code samples and documentation.
  • At the time of writing, without using containerized alternatives, GCF currently supports .NET Core 3.1 natively on the host. I could find no indication of when .NET 6 support will be made available.

Quickstart

  • Google documentation is good, presenting a single quickstart document demonstrating an HTTP-triggered function, with examples written using C# and instructions to use the CLI to create resources and remove them.

    » One minor critique was that there were instructions (big buttons!) directing the reader to go and do something using the web-based Console. I felt that the guide would have been better to use entirely CLI examples (which is what I’ve done in article 5 of this series).

Sample Code

  • Google supplies CLI templating, which includes a specific example of an “HTTP-triggered” function.
  • Because of the way Google has packaged away their service code, it wasn’t immediately obvious how/where/if we can define a service startup (for the purpose of configuring DI). However, once I realized that a startup class can be used, everything quickly fell into place.

Debugging/Testing

  • An elegant combination of streamlined function-code, with a hosting model that just works both locally and when deployed.

    » Local development was possible, in a way very similar to working with a conventional ASP.NET Web API service—e.g., being able to readily attach HTTP testing tools or our client application.

Other Observations

  • As with Azure Functions, GCF automatically provisioned an HTTP endpoint, so I would echo my comments above, as this makes developing with GCP equally convenient.
  • An activity that felt like it may have been superfluous was a requirement to explicitly grant permission to the Cloud Functions to use the Build Service (I felt this should be implicit).

Read the full Google Cloud post here.

AWS Lambda Function

aws logo

Note: I have a larger volume of comments relating to AWS, compared to Azure or GC. This reflects the greater amount of time and effort it took me to research the AWS version of the article in this series.

  • Specific support for .NET is well catered for.
  • At the time of writing, without using containerized alternatives, AWS currently supports .NET Core 3.1 natively on the host. According to Github: .NET 6 support on AWS, support for Lambda is coming “in the near future.”

screenshot of aws lambda docs

  • AWS documentation is something of a mixed bag. On one hand, it can be extensive and thorough, and provide thoroughly detailed information. On the other hand, a recurring frustration was “a lack of cross-document cohesiveness” (I’m guessing because they are separately maintained by various different product teams).

    » Strictly speaking, everything needed is “literally there” in the docs … it just kept feeling like the reader would need to “locate and coalesce resources” in order to make progress.
    » For example, the main developer guide AWS: Building Lambda functions with C# opens with a paragraph telling us that various .NET libraries are available (see the screenshot above), but then provides no guidance on how or where to use them, nor does it link to where that information can be found. This information does exist—but it does so separately at Github: AWS Lambda for .NET Core (which is a separate repo to https://github.com/awsdocs). This is an important resource for .NET developers using AWS, but the reader is left to find it themselves.

  • I sometimes didn’t feel that the examples were always useful.

    » For example, the main developer guide Developing an HTTP API in API Gateway mentions that a specific permission needs to be configured, but leaves the reader to search for the solution elsewhere (incidentally, the solution to this is buried away in an AWS knowledge base article).

  • Using the AWS CLI, services need to be created and configured in a verbose manner. Generally speaking, this makes provisioning and configuring things harder than [the competition has shown] they need to be.

Quickstart

Sample Code

  • AWS supplies CLI templating, but does not include a specific example of an “HTTP-triggered” function.

    » We are provided with an “empty” template, but initially it is not obvious how this can be used as an HTTP trigger.
    » Eventually, we learn that a separate API Gateway service is required, at which point the puzzle pieces start to fall into place.
    » The “empty” template can be partly used with the gateway. It still seems to be left to the reader to piece together the use of a separate Gateway proxy class in order to fully progress.
    » Commendably, in addition to the main sample, the templates also scaffold a unit test project (using xunit)—including a basic example of a unit test. Having taken things in the direction of unit testing, it would have been great to see examples that paved a path for how we could expand upon this, using our own mocked dependencies. Instead what we have is hard-coded or using AWS-provided test interfaces (Amazon.Lambda.TestUtilities).

Developing/Debugging/Testing

  • A basic “lambda function” does not support local hosting—something that, realistically, is a necessity for local development.

    » There are ways around this (such as hosting an ASP.NET application from within serverless infrastructure), but the default experience is that a “lambda function” needs to be deployed to the cloud in order to work.
    » AWS does provide a “Lambda Function Test Tool”—this requires a prebuilt .dll that is run from within its process and provides a constrained way to trigger the function. This is not a good development experience in my opinion.

Other Observations

  • AWS provides many options and often has very specific requirements (for example, defining identity and access permissions for various resources)—this can be overwhelming.
  • The various mandatory service-authorization steps sometimes felt cumbersome:

    » While I understood that providing choice and flexibility to the customer brings with it a multitude of entities, requiring a prescriptive matrix of permissions … I found that, for my simple use case, these activities only served to add a bunch of fiddly extra work that the other providers have shown need not be necessary.
    » For example, authorizing just the CLI tooling before even being able to use it was unnecessarily more complicated than when compared to either Azure or GCP.

Read the full AWS post here.

screenshot of apples and oranges
Image credit: Merelize on Freerange

Concluding Thoughts

  • I preferred the GCF approach to Function hosting—and, therefore, the development/debugging experience.
  • I preferred the Azure quickstart documentation—specifically because it provided most of what I needed (C# with CLI) concisely in a single document.
  • For simple use cases, AWS required a higher level of commitment in order to deliver the same results.
  • It’s easy to lose sight of real-world development when concerned with trivial examples such as those presented in this series. Breaking away from this, the flexibility and choice offered by AWS could represent a better choice for the evolution and growth of increasingly complex solutions over time.
  • The AWS approach to local-development—particularly the required use of the “Lambda Function Test Tool”—was not a satisfying or productive development experience.

I hope you’ll join me in the rest of the series! You can read about the client app setup in Part 2, Azure in Part 3, AWS in Part 4 or Google Cloud in Part 5

Useful References

Acknowledgments

Thanks to Mandy Mowers & Layla Porter for the overall document review.

Disclosure

I always disclose my position, association or bias at the time of writing. As an author, I received a fee from Progress Telerik in exchange for the content found in this series of articles. I have no association with Microsoft, Amazon nor Google—this series of articles is in no way intended to offer biased opinion nor recommendation as to your eventual choice of cloud provider.


Jim-McGowan
About the Author

Jim McG

A UK-based freelance developer using largely Microsoft technologies, Jim McG has been working with web and backend services since the late ‘90s. Today, he generally gravitates around cloud-based solutions using C#, .NET Core and Azure, with a particular interest in serverless technologies. Most recently, he's been transitioning across to Unity and the amazing tech that is Augmented Reality.

Related Posts

Comments

Comments are disabled in preview mode.