The .NET Core AWS SDK 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 and DynamoDB.
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.
⚠ 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)
- Create an S3 bucket (or use an existing)
- Add a few objects
-
❗ 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!
[ { "AllowedHeaders": [ "*" ], "AllowedMethods": [ "GET", "HEAD" ], "AllowedOrigins": [ "*" ], "ExposeHeaders": [], "MaxAgeSeconds": 3000 } ]
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:
{
"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:
@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.
Top comments (0)