-2

Trying to send an email with an attachment. However I am getting an error:

"Cannot convert from 'System.Threading.Tasks.Task' to 'System.Net.Mail.Attachment'

My error occurs in the line Attachments.Add(GetAttachment(attachmentFileName));

I have tried various conversions (see code) but I dont quite see what the issue is. I know the solution is right in front of me but I dont see it.

public class NonFERosterEmail : BaseNotificationEmail<OfferViewModel>
{
    public NonFERosterEmail(OfferViewModel vm, string emailList, string attachmentFileName) : base(vm)
    {
        To.AddRange(GetTo(emailList));
        Body = GetBody();
        Subject = GetSubject();
        //Attachments.Add(new Attachment(GetAttachment(attachmentFileName)));
        Attachments.Add(GetAttachment(attachmentFileName));
        From = new MailAddress(ConfigurationManager.AppSettings["RedirectEmailTo"]);
    }

    //public async Task<List<Attachment>> GetAttachment(string attachmentFileName)
    public async Task<Attachment> GetAttachment(string attachmentFileName)
    {
        //var ret = new List<Attachment>();

        CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.AppSettings["azureStorageAccount"]); 
        CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
        CloudBlobContainer container = blobClient.GetContainerReference("attachments");
        CloudBlockBlob blob = container.GetBlockBlobReference(attachmentFileName);

        var contentType = MimeMapping.GetMimeMapping(attachmentFileName);
        Stream target = new MemoryStream();
        await blob.DownloadToStreamAsync(target);
        target.Position = 0;
        //ret.Add(new Attachment(target, attachmentFileName, contentType));

        Attachment ret = new Attachment(target, attachmentFileName, contentType);

        return ret;
    }

//remainder of code left out for brevity
}

I expect the GetAttachment to return a correct Attachment object which would be added to the Mail object and sent successfully.

Roman Marusyk
  • 23,328
  • 24
  • 73
  • 116
bradoxbl
  • 89
  • 9

3 Answers3

1

To get the value from a Task<T>, you must make your method async and await the task.

SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964
1

You need to await when call method that returns Task, so instead of this

Attachments.Add(GetAttachment(attachmentFileName));

Use:

Attachments.Add(await GetAttachment(attachmentFileName));

or

Attachments.Add(GetAttachment(attachmentFileName).GetAwaiter().GetResult());
Roman Marusyk
  • 23,328
  • 24
  • 73
  • 116
1

I believe the answers from @SLaks and @Roman Marusyk are correct, but it looks like you are calling GetAttachment from the constructor, which is not asynchronous. As such you would not be able to use await without using an async method. Try using the result property of GetAttachment as shown below.

Attachments.Add(GetAttachment(attachmentFileName).Result);

A better solution would be to use .GetAwaiter().GetResult(), which as @Roman Marusyk pointed out and shown in this post, if the method fails it will throw the exception directly rather than throwing an AggregateException.

A better solution would be to use the following

Attachments.Add(GetAttachment(attachmentFileName).GetAwaiter().GetResult());
ivcubr
  • 1,988
  • 9
  • 20
  • 28
  • `Task.GetAwaiter().GetResult()` is preferred over `Task.Result` see https://stackoverflow.com/questions/17284517/is-task-result-the-same-as-getawaiter-getresult – Roman Marusyk Jul 12 '19 at 17:02
  • 1
    @RomanMarusyk thanks the suggestion, I have updated my answer accordingly – ivcubr Jul 12 '19 at 17:10