Search code examples
amazon-web-servicesamazon-s3aws-sdkaws-sdk-net

Problems with AWS SDK .NET


I am trying to retrieve images from my bucket to send to my mobile apps, I currently have the devices accessing AWS directly, however I am adding a layer of security and having my apps (IOS and Android) now make requests to my server which will then respond with DynamoDB and S3 data.

I am trying to follow the documentation and code samples provided by AWS for .Net and they worked seamlessly for DynamoDB, I am running into problems with S3.

S3 .NET Documentation

My problem is that if I provide no credentials, I get the error:

Failed to retrieve credentials from EC2 Instance Metadata Service

This is expected as I have IAM roles set up and only want my apps and this server (in the future, only this server) to have access to the buckets.

But when I provide the credentials, the same way I provided credentials for DynamoDB, my server waits forever and doesn't receive any responses from AWS.

Here is my C#:

<%@ WebHandler Language="C#" Class="CheckaraRequestHandler" %>

using System;
using System.Web;
using System.Collections.Generic;
using Amazon.DynamoDBv2;
using Amazon.DynamoDBv2.Model;
using Amazon.DynamoDBv2.DocumentModel;
using Amazon;
using Amazon.Runtime;
using Amazon.S3;
using Amazon.S3.Model;
using System.IO;
using System.Threading.Tasks;


public class CheckaraRequestHandler : IHttpHandler
{

    private const string bucketName = "MY_BUCKET_NAME";

    private static readonly RegionEndpoint bucketRegion = RegionEndpoint.USEast1;
    public static IAmazonS3 client = new AmazonS3Client("MY_ACCESS_KEY", "MY_SECRET_KEY", RegionEndpoint.USEast1);



    public void ProcessRequest(HttpContext context)
    {

        if (context.Request.HttpMethod.ToString() == "GET")
        {
            string userID = context.Request.QueryString["User"];
            string Action = context.Request.QueryString["Action"];



            if (userID == null)
            {
                context.Response.ContentType = "text/plain";
                context.Response.Write("TRY AGAIN!");
                return;
            }



            if (Action == "GetPhoto")
            {

                ReadObjectDataAsync(userID).Wait();


            }

            var client = new AmazonDynamoDBClient("MY_ACCESS_KEY", "MY_SECRET_KEY", RegionEndpoint.USEast1);

            Console.WriteLine("Getting list of tables");

            var table = Table.LoadTable(client, "TABLE_NAME");
            var item = table.GetItem(userID);


            if (item != null)
            {
                context.Response.ContentType = "application/json";
                context.Response.Write(item.ToJson());
            }
            else
            {
                context.Response.ContentType = "text/plain";
                context.Response.Write("0");
            }
        }

    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }

    static async Task ReadObjectDataAsync(string userID)
    {



        string responseBody = "";
        try
        {
            string formattedKey = userID + "/" + userID + "_PROFILEPHOTO.jpeg";
            //string formattedKey = userID + "_PROFILEPHOTO.jpeg";
            //formattedKey = formattedKey.Replace(":", "%3A");
            GetObjectRequest request = new GetObjectRequest
            {
                BucketName = bucketName,
                Key = formattedKey
            };


            using (GetObjectResponse response = await client.GetObjectAsync(request))
            using (Stream responseStream = response.ResponseStream)
            using (StreamReader reader = new StreamReader(responseStream))
            {
                string title = response.Metadata["x-amz-meta-title"]; // Assume you have "title" as medata added to the object.
                string contentType = response.Headers["Content-Type"];
                Console.WriteLine("Object metadata, Title: {0}", title);
                Console.WriteLine("Content type: {0}", contentType);

                responseBody = reader.ReadToEnd(); // Now you process the response body.
            }
        }
        catch (AmazonS3Exception e)
        {
            Console.WriteLine("Error encountered ***. Message:'{0}' when writing an  object", e.Message);
        }
        catch (Exception e)
        {
            Console.WriteLine("Unknown encountered on server. Message:'{0}' when writing an object", e.Message);
        }
    }

}

When I debug, this line waits forever:

using (GetObjectResponse response = await client.GetObjectAsync(request)) 

This is the same line that throws the credentials error when I don't provide them. Is there something that I am missing here?

Any help would be greatly appreciated.


Solution

  • I suspect that the AWS .NET SDK has some isses with it specifically with the async call to S3.

    The async call to dynamoDB works perfect, but the S3 one hangs forever.

    What fixed my problem was simply removing the async functionality (even tho in the AWS docs, the async call is supposed to be used)

    Before:

    using (GetObjectResponse response = await client.GetObjectAsync(request))
    

    After:

    using (GetObjectResponse response =  myClient.GetObject(request))
    

    Hopefully this helps anyone else encountering this issue.