ok I have a webapi which gets/adds/updates/deletes customers, the backend is CosmosDB.
Users are able to upload image for each customer, the file is stored in Azure Blob Storage, but the filename is stored in the CosmosDB property.
[HttpPost]
public async Task<IHttpActionResult> Adduser([FromBody]User user)
{
var telemetry = new TelemetryClient();
try
{
var userStore = CosmosStoreHolder.Instance.CosmosStoreUser;
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
//Then we validate the content type
if (!Request.Content.IsMimeMultipartContent("form-data"))
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
#region File upload
//Initalize configuration settings
var accountName = ConfigurationManager.AppSettings["storage:account:name"];
var accountKey = ConfigurationManager.AppSettings["storage:account:key"];
var profilepicturecontainername = ConfigurationManager.AppSettings["storage:account:profilepicscontainername"];
//Instance objects needed to store the files
var storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer imagesContainer = blobClient.GetContainerReference(profilepicturecontainername);
var provider = new AzureStorageMultipartFormDataStreamProvider(imagesContainer);
// Validate extension and image size
foreach (MultipartFileData file in provider.FileData)
{
var fileName = file.Headers.ContentDisposition.FileName.Trim('\"').Trim();
if (fileName.EndsWith(".png"))
{
var img = Image.FromFile(file.LocalFileName);
if (img.Width != 200 && img.Height != 200)
{
string guid = Guid.NewGuid().ToString();
return BadRequest($"Error Lulo. Unsupported extension, only PNG is valid. Or unsuported image dimensions (200px x 200px)");
}
}
}
//Try to upload file
try
{
await Request.Content.ReadAsMultipartAsync(provider);
}
catch (Exception ex)
{
string guid = Guid.NewGuid().ToString();
var dt = new Dictionary<string, string>
{
{ "Error Lulo: ", guid }
};
telemetry.TrackException(ex, dt);
return BadRequest($"Error Lulo. An error has occured. Details: {guid} {ex.Message}: ");
}
// Retrieve the filename of the file you have uploaded
var filename = provider.FileData.FirstOrDefault()?.LocalFileName;
if (string.IsNullOrEmpty(filename))
{
string guid = Guid.NewGuid().ToString();
var dt = new Dictionary<string, string>
{
{ "Error Lulo: ", guid }
};
return BadRequest($"Error Lulo. An error has occured while uploading your file. Please try again.: {guid} ");
}
//Rename file
CloudBlockBlob blobCopy = imagesContainer.GetBlockBlobReference(user.Id + ".png");
if (!await blobCopy.ExistsAsync())
{
CloudBlockBlob blob = imagesContainer.GetBlockBlobReference(filename);
if (await blob.ExistsAsync())
{
await blobCopy.StartCopyAsync(blob);
await blob.DeleteIfExistsAsync();
}
}
#endregion
if (string.IsNullOrEmpty(user.CustomerId) && string.IsNullOrEmpty(user.PartnerId))
{
return BadRequest("ClientID or PartnerId must be filled in.");
}
var added = await userStore.AddAsync(user);
return Ok(added);
}
catch (Exception ex)
{
string guid = Guid.NewGuid().ToString();
var dt = new Dictionary<string, string>
{
{ "Error Lulo: ", guid }
};
telemetry.TrackException(ex, dt);
return BadRequest("Error Lulo: " + guid);
}
}
Now, I need to return to the web api, the image in someway the frontend developers can render it. The Azure Blob Container is not public, so returning the Url will not be enough.
The front end is react.
This is my get method (which returns the picture Url, only)
[HttpGet]
public async Task<IHttpActionResult> GetUser(string email)
{
var telemetry = new TelemetryClient();
try
{
var userStore = CosmosStoreHolder.Instance.CosmosStoreUser;
var roleStore = CosmosStoreHolder.Instance.CosmosStoreRole;
var user = await userStore.Query().FirstOrDefaultAsync(x => x.EmailAddress == email);
if (user == null)
{
return Unauthorized();
}
var role = await roleStore.Query().FirstOrDefaultAsync(x => x.Id == user.RoleId);
user.RoleName = role.RoleName;
return Ok(user);
}
catch (Exception ex)
{
string guid = Guid.NewGuid().ToString();
var dt = new Dictionary<string, string>
{
{ "Error Lulo: ", guid }
};
telemetry.TrackException(ex, dt);
return BadRequest("Error Lulo: " + guid);
}
}
And just in case, the User POCO here below:
public class User : ISharedCosmosEntity
{
[JsonProperty("Id")]
public string Id { get; set; }
public string EmailAddress { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool Enabled { get; set; }
public string ProfilePictureUrl { get; set; }
public string RoleName { get; set; }
public string CustomerName { get; set; }
public string PartnerName { get; set; }
public string CustomerId{ get; set; }
public string PartnerId { get; set; }
public string RoleId { get; set; }
[CosmosPartitionKey]
public string CosmosEntityName { get; set; }
}