This sample demonstrates how ASP.NET Core 8.0 can be used to build a cloud native application that consists of a frontend web app and an API that communicate asynchronously via messaged queues. Messaging between frontend and API is implemented using Dapr and both frontend and API are hosted in Azure Container Apps.
Contoso Ads on Containers is a modernized version of the original Contoso Ads sample app for Azure Cloud Services and Azure WebJobs built from scratch for Azure Container Apps.
The repository consists of the following projects and folders:
- src/ContosoAds.Web - Contoso Ads ASP.NET Core Razor Pages web frontend. The UI shows a list of ads, and allows users to post, edit, and delete ads
- test/ContosoAds.Web.UnitTests - Unit tests for the web application that focus on testing the core application logic
- test/ContosoAds.Web.IntegrationTests - Integration tests for the web application that focus on testing the HTTP request/response interaction
- src/ContosoAds.ImageProcessor Image Processor API - ASP.NET Core Minimal API that renders thumbnail images for uploaded images
- test/ContosoAds.ImageProcessor.UnitTests - Unit tests for the image processor API that focus on testing the core application logic
- test/ContosoAds.ImageProcessor.IntegrationTests - Integration tests for the image processor API that focus on testing the HTTP request/response interaction
- components - Dapr component files
- infra - Azure Bicep templates
- deploy - Additional files used for app deployment
- .github/workflows - GitHub Actions workflows
- docs - Additional documentation
This sample app uses a variety of technologies:
- Azure Container Apps
- Azure Database for PostgreSQL Flexible Server
- Azure Storage
- Azure Container Instances
- Azure Application Insights
- Azure Bicep
- ASP.NET Core Razor Pages
- ASP.NET Core Minimal API
- Entity Framework Core 8.0
- Dapr
- C# 12
You'll a small set of tools and skills to get started:
- macOS, Linux, or Windows 10/11
- The Azure Developer CLI
- Docker Desktop
- A Microsoft Azure subscription
You an sign up for a Microsoft Azure subscription for free here.
Contoso Ads consist of two Azure Container Apps that are running in the same Container App environment. The web application allows you to create, edit and delete ads and optionally upload an image for an ad. All uploaded images are stored on Azure blob storage using a Dapr output binding. For every uploaded image, a request is queued up to an image processor API to render a thumbnail image. Messaging between the web app and the image processor utilizes Azure storage queues and Dapr input/output bindings. Ads are stored in a PostgreSQL database accessed through Entity Framework Core.
The web application is accessible from the Internet, while the image processor API is only accessible from within the Container App environment.
The Azure Database for PostgreSQL Flexible server is injected into the same virtual network that hosts the Azure Container App environment and is therefore not exposed to the internet. The Azure blob storage container that hosts the images is exposed to the internet since the images must be accessible by a browser.
An Azure Container Instance (not depicted) injected in the virtual network is used to run database migrations.
Contoso Ads on Containers can be deployed using the Azure Developer CLI to provision the required Azure services and to deploy the application in a few simple steps.
azd
will prompt you to select an Azure subscription, an environment name (e.g., contosoads-demo
) and an Azure region when
deploying the app for the first time.
Run the following commands in your preferred shell (e.g., zsh, bash, PowerShell, โฆ)
# Log in to azd (only required before first use)
azd auth login
# Set a Postgres admin login and password
azd env set POSTGRES_LOGIN contosoads
# If you don't have OpenSSL installed or don't want to use a
# a random password, set POSTGRES_LOGIN_PASSWORD to a secure
# password of your choice
azd env set POSTGRES_LOGIN_PASSWORD "$(openssl rand -hex 20)##"
# Provision the infrastructure, build and deploy the application's container images
azd up
If the deployment succeeds, you should see output similar to the following screenshot. Copy
and paste the FQDN displayed for the webapp
service to your browser and start using
the app!
The Bicep templates used by azd
create a series of resources in your Azure subscription. These are used primarily for
hosting the application and its database, but there are also additional resources that aid with monitoring and observing how the
app is running in the cloud environment.
Resource | Resource Type | Purpose |
---|---|---|
contosoads-web | An Azure Container App for the web app | The web app is the Contoso Ads' web frontend where you can create, edit, and delete ads. |
contosoads-imageprocessor | An Azure Container App for the image processor API | This API reads requests from a queue to render images stored in blob storage and creates thumbnail versions of these images. |
ca<random_string>-env | An Azure Container Apps environment | This environment serves as the logical container for all of the instances of all of the container apps comprising the app. |
ca<random_string>-insights | Application Insights | This provides traces, logs, and metrics to troubleshoot the application. |
ca<random_string>-logs | Log Analytics workspace | This is the data sink for Application Insights and log output captured by the application containers. |
ca<random_string>-vnet | Virtual network | The Container Apps environment, the PostgreSQL server, and the Container Instance are all connected through this network using different subnets. |
ca<random_string>-infra-nsg | Network security group | A set of network rules that are applied to the Container App's subnet. |
contosoads.postgres.database.azure.com | Azure Private DNS zone | Provides name resolution for the privately hosted PostgreSQL server. |
ca<random_string> | Azure Storage account | Provides both the blob storage and the storage queues. |
ca<random_string> | Azure Database for PostgreSQL Flexible Server | Hosts the application's database and ASP.NET Core data protection keys. |
ca<random_string> | Azure Container Registry | Stores container images built using azd up and azd deploy . |
ca<random_string>-migration | Azure Container Instance | This runs the database migration script to prepare the database during deployment. |
The resources are shown here in the Azure portal:
Click on the contosoads-web
container app to open it up in the Azure portal. In the Overview
tab you'll see a URL.
Clicking that URL will open the app's frontend up in the browser. It's the
same URL that is displayed after running azd up
or azd deploy
.
Click the CREATE AN AD
button and create your first ad.
After creating an ad, the web app will navigate back to the list view. No thumbnail is shown yet.
After a few seconds, once the image processor has created the the thumbnail, the web page will refresh itself display and the thumbnail.
If you want to change the sample app's source code and run these changes in Azure, you will need to install additional tools:
- .NET 7.0 SDK
- Dapr
- (Optional, but recommended) An IDE or code editor (e.g., Visual Studio, Visual Studio Code, Rider)
The Azure Developer CLI makes it easy to change the sample and deploy it to Azure. After updating the application's source code, run
azd deploy
to build container images, upload them to your deployment's Azure Container Registry, and deploy them as new Container App revisions.
See Building and running the sample app using the .NET SDK and Dapr for additional information how to develop the sample app.
These steps are optional and not required to deploy the application to Azure. Use them to learn about building and running the application on your local machine and alternate deployment techniques.
See this document for instructions on how to build and run the sample app on your PC or Mac using the .NET SDK and the Dapr CLI.
See this document for instructions on how to run the sample app on your PC or Mac using Docker.
See this document for instructions on how to set up a GitHub Actions workflow to deploy the sample app.