1

I'm attempting to understand async and Task with await, not sure if I quite get it yet as my application isn't responding the way I thought it worked.

I have an MVC project and inside a Controller is a method that runs on Save. This method does a few things, but the main item I am focusing on is the sending of an email to SendGrid.

[HttpPost]
[ValidateAntiForgeryToken]
private void SaveAndSend(ModelView model)
{
    //This is never used, but is needed in "static async Task Execute()"
    ApplicationDBContext db = new ApplicationDBContext();

    //First try (like the SendGrid example)
        Execute().Wait();
        //More code, but wasn't being executed (even with a breakpoint)
        //...


    //Second try, removed the .Wait()
        Execute();
        //More code and is being executed (good)
        //...
}

Inside Execute():

static async Task Execute()
{
    var apiKey = "REMOVED";
    var client = new SendGridClient(apiKey);
    var from = new SendGrid.Helpers.Mail.EmailAddress("[email protected]", "Example User");
    var subject = "Sending with SendGrid is Fun";
    var to = new SendGrid.Helpers.Mail.EmailAddress("[email protected]", "Example User");
    var plainTextContent = "and easy to do anywhere, even with C#";
    var htmlContent = "<strong>and easy to do anywhere, even with C#</strong>";
    var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
    var iResponse = await client.SendEmailAsync(msg);

    //The above ^ is executed (sent to SendGrid successfuly)

    //The below is not being executed if I run the code with no breakpoints
    //If I set a breakpoint above, I can wait a few seconds, then continue and have the code below executed

    //This is an Object I have to save the Response from SendGrid for testing purposes
    SendGridResponse sendGridResponse = new SendGridResponse
    {
        Date = DateTime.Now,
        Response = JsonConvert.SerializeObject(iResponse, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore })
    };

    //This is needed to save to the database, was hoping to avoid creating another Context
    ApplicationDBContext db = new ApplicationDBContext();

    db.SendGridResponses.Add(sendGridResponse);
    db.SaveChanges();

}

Now that I have outlined my code (most likely horrible practices), I was hoping to better understand async Task and improve what I am attempting to accomplish.

How can I wait for var iResponse = await client.SendEmailAsync(msg); and Save it to my database properly. Allowing the application to continue (not interupt the user experience).

Please let me know if I should include more information.

3
  • 1
    Does SendGrid really recommend using Wait()? You should make your controller async and await the call, do not block with Wait. Commented Dec 9, 2017 at 19:22
  • I'll check out the other Question @Clint, thank you. Commented Dec 9, 2017 at 19:29
  • SendGrid does have .Wait() in the Getting Started @Crowcoder. Commented Dec 9, 2017 at 19:30

1 Answer 1

2

You can make your controller async by return Task and then await the call instead of Wait.

 [HttpPost]
 [ValidateAntiForgeryToken]
 public async Task<IActionResult> SaveAndSend(ModelView model)
 {
      //This is never used, but is needed in "static async Task Execute()"
      ApplicationDBContext db = new ApplicationDBContext();

      // Await the Execute method call, instead of Wait()
      await Execute();
    .....
}
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.