Skip to main content

Command Palette

Search for a command to run...

Hosting Blazor WebAssembly Applications on AWS CloudFront

Updated
3 min read
Hosting Blazor WebAssembly Applications on AWS CloudFront
R

Somebody who likes to code

Blazor is becoming a popular choice for developing modern web applications using C# and .NET, offering two distinct hosting models:

  • Blazor Server: In this model, the application runs on the server, and UI updates are sent to the browser through a SignalR connection.

  • Blazor WebAssembly: In this model, the application runs directly in the browser using WebAssembly.

Within the Blazor WebAssembly model, there are two options for deploying our application:

  • Hosted deployment: In this option, the Blazor WebAssembly application is delivered from an ASP.NET Core app.

  • Standalone deployment: In this deployment, the Blazor WebAssembly application is delivered from a static web server. This option allows us to use various hosting environments like Amazon S3, GitHub Pages, Azure Static Web Apps, Azure Storage, and more.

In this article, we will deploy a Blazor WebAssembly application in an AWS S3 bucket and deliver it to our users using a CDN such as AWS CloudFront.

Pre-requisites

Blazor WebAssembly App

We will use the default Blazor WebAssembly application provided by the templates. Run the following commands:

dotnet new blazorwasm -o MyApp
dotnet new sln -n Blazor
dotnet sln add --in-root MyApp

AWS SAM template

At the solution level, create a template.yml file with the following content:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  SAM

Resources:
  MyBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: "<MY_BUCKET_NAME>"
      PublicAccessBlockConfiguration:
        BlockPublicAcls: true
        BlockPublicPolicy: true
        IgnorePublicAcls: true
        RestrictPublicBuckets: true

  MyCloudFrontOriginAccessControl:
    Type: AWS::CloudFront::OriginAccessControl
    Properties:
      OriginAccessControlConfig:
        Name: !Sub "OAC for ${MyBucket}"
        OriginAccessControlOriginType: s3
        SigningBehavior: always
        SigningProtocol: sigv4

  MyCloudFrontDistribution:
    Type: AWS::CloudFront::Distribution
    DependsOn:
      - MyBucket
    Properties:
      DistributionConfig:
        Origins:
          - DomainName: !GetAtt MyBucket.DomainName
            Id: !Sub "origin-${MyBucket}"
            S3OriginConfig:
              OriginAccessIdentity: ""
            OriginAccessControlId: !GetAtt MyCloudFrontOriginAccessControl.Id
        Enabled: "true"
        PriceClass: "PriceClass_200"
        IPV6Enabled : "false"
        DefaultRootObject: index.html
        ViewerCertificate:
          CloudFrontDefaultCertificate: true
        DefaultCacheBehavior:
          AllowedMethods:
            - DELETE
            - GET
            - HEAD
            - OPTIONS
            - PATCH
            - POST
            - PUT
          CachedMethods :
            - GET
            - HEAD
          Compress: true
          TargetOriginId: !Sub "origin-${MyBucket}"
          ForwardedValues:
            QueryString: "false"
            Cookies:
              Forward: none
          ViewerProtocolPolicy: allow-all

  MyBucketPolicy:
    Type: AWS::S3::BucketPolicy
    Properties:
      Bucket: !Ref MyBucket
      PolicyDocument:
        Version: 2008-10-17
        Statement:
          - Action:
            - 's3:GetObject'
            Effect: Allow
            Principal:
              Service: cloudfront.amazonaws.com
            Resource: !Sub "${MyBucket.Arn}/*"
            Condition:
              StringEquals:
                AWS:SourceArn: !Sub "arn:aws:cloudfront::${AWS::AccountId}:distribution/${MyCloudFrontDistribution.Id}"

Outputs:
  CloudFrontURL:
    Description: URL of CloudFront distribution.
    Value: !GetAtt MyCloudFrontDistribution.DomainName

The script above defines the following resources:

  • AWS::S3::Bucket: This resource creates the AWS S3 bucket, blocking all public access.

  • AWS::CloudFront::OriginAccessControl: This resource creates a new origin access control (OAC). Once created, it can be added to an origin in a CloudFront distribution. This allows CloudFront to send authenticated requests to the origin, allowing us to block public access.

  • AWS::CloudFront::Distribution: This resource creates the distribution that instructs CloudFront where to locate the content to deliver and provides details on how to track and manage it.

  • AWS::S3::BucketPolicy: This resource configures our AWS S3 bucket to allow access for requests from the CloudFront distribution with OAC.

Deploying our application

Run the following commands to deploy the resources to AWS:

sam build
sam deploy --guided

Once the resources are deployed, it's time to deploy our Blazor application to AWS S3:

dotnet publish -c Release
aws s3 sync '.\MyApp\bin\Release\net8.0\publish\wwwroot' s3://<MY_BUCKET_NAME>

Testing our application

Browse to the output URL to view the Blazor application up and running:

You can find all the code here. Thanks, and happy coding.

More from this blog

raulnq

171 posts

Somebody who likes to code