> ## Documentation Index
> Fetch the complete documentation index at: https://docs.tensor9.com/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS .NET SDK Guide

> Configure the AWS SDK for .NET to use a Cloud Adapter endpoint and inspect service failures.

This example uses `AWSSDK.S3`. Your code keeps using `IAmazonS3`; the client configuration directs requests to Cloud Adapter.

## Choose how to set the endpoint

### Set it for the process

```bash theme={null}
export AWS_ENDPOINT_URL_S3="https://adapter.example.test"
```

AWS SDK for .NET reads the service-specific setting when `ServiceURL` is not assigned:

```csharp theme={null}
using System;
using Amazon.Runtime;
using Amazon.S3;

var credentials = new StoredProfileAWSCredentials("adapter-test");
var config = new AmazonS3Config
{
    AuthenticationRegion = "us-east-1",
    ForcePathStyle = true,
    Timeout = TimeSpan.FromSeconds(30),
    MaxErrorRetry = 2,
};
IAmazonS3 s3 = new AmazonS3Client(credentials, config);
```

### Set it on one client

```bash theme={null}
export T9_CLOUD_ADAPTER_ENDPOINT="https://adapter.example.test"
```

```csharp theme={null}
using System;
using Amazon;
using Amazon.Runtime;
using Amazon.S3;

var credentials = new StoredProfileAWSCredentials("adapter-test");
var config = new AmazonS3Config
{
    ServiceURL = Environment.GetEnvironmentVariable("T9_CLOUD_ADAPTER_ENDPOINT"),
    AuthenticationRegion = "us-east-1",
    ForcePathStyle = true,
    Timeout = TimeSpan.FromSeconds(30),
    MaxErrorRetry = 2,
};

IAmazonS3 s3 = new AmazonS3Client(credentials, config);
```

`ServiceURL` selects the adapter endpoint. `AuthenticationRegion` keeps AWS signing behavior explicit. The adapter's target-cloud identity remains in service adapter configuration, not in the .NET process.

An explicit `ServiceURL` takes precedence over `AWS_ENDPOINT_URL_S3`.

## Verify a lifecycle

```csharp theme={null}
using System;
using System.IO;
using Amazon.S3.Model;
using System.Text;

var bucket = Environment.GetEnvironmentVariable("TEST_BUCKET")!;
var key = $"dotnet/{DateTimeOffset.UtcNow.ToUnixTimeMilliseconds()}-hello.txt";
var expected = "hello through Cloud Adapter\n";

var put = await s3.PutObjectAsync(new PutObjectRequest
{
    BucketName = bucket,
    Key = key,
    ContentBody = expected,
    ContentType = "text/plain",
});

var head = await s3.GetObjectMetadataAsync(bucket, key);
using var get = await s3.GetObjectAsync(bucket, key);
using var reader = new StreamReader(get.ResponseStream, Encoding.UTF8);
var actual = await reader.ReadToEndAsync();
if (actual != expected) throw new InvalidOperationException("Downloaded bytes differ");

await s3.DeleteObjectAsync(bucket, key);
```

Inspect the native target object after the put. Record `put.ResponseMetadata.RequestId`, `put.HttpStatusCode`, the target object name, and the adapter version with your test evidence.

## Handle errors

```csharp theme={null}
try
{
    await s3.GetObjectMetadataAsync(bucket, "missing-key");
}
catch (AmazonS3Exception error)
{
    Console.Error.WriteLine(new
    {
        error.ErrorCode,
        error.StatusCode,
        error.RequestId,
        error.Message,
    });
}
catch (AmazonServiceException error)
{
    Console.Error.WriteLine($"Service failure: {error.Message}");
}
```

Network and cancellation failures may have no service response. Do not treat missing response metadata as a translated AWS error. After a timeout on a mutation, inspect target state before retrying.

## Production checklist

* Reuse `IAmazonS3`; do not construct a client per request.
* Pass cancellation tokens from the application boundary.
* Test the exact retry, paginator, multipart, and conditional behaviors you use.
* Keep origin credentials and backend credentials separate.
* Do not log signed headers, request bodies, or secret values.
* Compare operations with [S3 target coverage](/cloud-adapter/service-catalog/aws/databases-storage/s3).

Use [Debugging Your Adapters](/cloud-adapter/debugging/overview) when the SDK response and native target state disagree.
