Use the .NET Core AWS SDK on Blazor WASM
Tags: dotnet, aws, blazor, webassembly
Published: 2021-01-25 15:38:41

---
title: Use the .NET Core AWS SDK on Blazor WASM
published: true
description: The .NET AWS SDK v3.5.2 now officially supports Blazor WASM
tags: dotnet,aws,blazor,wasm
cover_image: https://i.imgur.com/NHk3zGE.jpg
---

The .NET [Core AWS SDK](https://www.nuget.org/packages/AWSSDK.Core/) has released an update that allows it to run fully in the browser thanks to WASM.

In this post, id like to show an example that enumerates S3 objects fully client side! You should also be able to utilize services like [Cognito](https://aws.amazon.com/cognito/) and [DynamoDB](https://aws.amazon.com/dynamodb/).

![Screenshot of Blazor WASM S3 Object Browser](https://i.imgur.com/dDKV2vD.png)

Before we get started, id like to point out some caveats that I ran into while testing this functionality.

⚠ .NET 5 not yet supported! This is because Crypto libraries no longer exist in .NET 5 WASM, so AWS can't sign requests. [More info here.](https://github.com/dotnet/runtime/issues/40074)
⚠ Today, you **must** use the `UseAlternateUserAgentHeader` wherever possible. More on this below.

Lets get started!

## Prerequisites

Grab the latest Core 3.1 SDK: https://dotnet.microsoft.com/download/dotnet-core/3.1

## AWS (bucket & user)

1. Create an S3 bucket (or use an existing)
2. Add a few objects
3. ❗ Add a CORS policy. Remember, you're in the browser now! The AWS SDK requests to the AWS API will show up right in the networking tab of your browser's dev tools. Very cool!

    ```json
    [
        {
            "AllowedHeaders": [
                "*"
            ],
            "AllowedMethods": [
                "GET",
                "HEAD"
            ],
            "AllowedOrigins": [
                "*"
            ],
            "ExposeHeaders": [],
            "MaxAgeSeconds": 3000
        }
    ]
    ```

4. Create an IAM user and select "Programmatic access", apply an existing policy called `AmazonS3ReadOnlyAccess` to the user, download the resulting credentials csv or copy the access key ID and secret and store somewhere.

🎉 **You are ready to code!** 🎊

## Code

Create a folder, and inside place a `global.json` with the following contents:

```json
{
  "sdk": {
    "version": "3.1.403"
  }
}
```

This tells the dotnet CLI that any dotnet commands you run inside that folder should target 3.1.

Next, scaffold out a new blazor project by running the following commands:

- `dotnet new blazorwasm --name s3blazorwasm`
- `cd s3blazorwasm`
- `dotnet add package AWSSDK.S3`

AWSSDK.S3 has a dependency on AWSSDK.Core.

In `_imports.razor` import the AWS stuff:

```
@using Amazon
@using Amazon.S3
@using Amazon.S3.Model
```

For speed and brevity, open up `Counter.razor` clear out everything and place the following:

```c#
@page "/counter"

<h1>S3 List Objects</h1>

@if (bucketObjectNames == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <ul>
        @foreach (var bucketObjectName in bucketObjectNames)
        {
            <li>@bucketObjectName</li>
        }
    </ul>
}

@code {
    private List<string> bucketObjectNames;

    protected override async Task OnInitializedAsync()
    {
        var config = new AmazonS3Config
        {
            RegionEndpoint = RegionEndpoint.USEast1,
            UseAlternateUserAgentHeader = true
        };

        var s3Client = new AmazonS3Client("YOURKEY", "YOURSECRET", config);

        var bucketObjectResponse = await s3Client.ListObjectsV2Async(new ListObjectsV2Request
        {
            BucketName = "YOURBUCKET"
        });

        bucketObjectNames = bucketObjectResponse.S3Objects.Select(x => x.Key).ToList();
    }
}
```

ℹ Special note on `UseAlternateUserAgentHeader`. Internally, the AWS SDK generates a user agent on its own and includes it as part of the signature. When your browser makes a request it ends up using the User-Agent that Chrome generates. This fails the signature check. You need `UseAlternateUserAgentHeader` to tell AWS to use the generated header (looks like: `x-amz-user-agent: aws-sdk-dotnet-netstandard/3.5.7.8 aws-sdk-dotnet-core/3.5.2.0 .NET_Core/(3.2-wasm/1a6e64a9381) OS/web ClientAsync`) which gets signed, and sent in the request and validated by AWS properly.

Fire up your app, you should see a list of your objects when you navigate to /counter! Of course feel free to update the page name, route and navigation.

Hopefully this helps you get started, I noticed as this is so new, there are not many docs or information available on any of this yet.

Also, don't forget to delete the user you created and/or remove policies from it, as well as remove the CORS policy from your bucket.