I am having a problem retrieving an HTTP response code from SendGrid, and then updating a label based on that response. Since the SendGrid call uses an async method I am not able to get return a response.statuscode;
this is my code:
protected void BtnSend_Click(object sender, EventArgs e)
{
lblmsg.InnerText = SendMail(txtEmailId.Text.ToString(),
txtMessage.Text.ToString()); //------------
}
private String SendMail(String EmailId, String Message)
{
var status="";
Execute(EmailId, Message).Wait();
return status;
}
async Task Execute(String EmailId, String Message)
{
var apiKey = "abcdefghijklmnopqrstuvwxyz1234567890";
var client = new SendGridClient(apiKey);
var from = new EmailAddress("myemail#gmail.com", "Sender");
var subject = "Testing Email";
var to = new EmailAddress(EmailId, "Reciever");
var plainTextContent = "You have recieved this message from me";
var htmlContent = Message + "<br><i>-Message sent by me</i>";
var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
var response = await client.SendEmailAsync(msg).ConfigureAwait(false);
var status = response.StatusCode;
}
Your method does not allow a return value, since you declared it as async Task. That means it's an async method that returns nothing (it just a returns a Task so the caller knows when it's done, but no actual value).
If you want to return something from an async method, you need to use a Task<T> return type, where T is the type of value you want to return.
So in this case, it should be:
async Task<HttpStatusCode> Execute(String EmailId, String Message)
Then you can return response.StatusCode
Here's some additional reading that might help you understand async code better:
Asynchronous programming
The Task asynchronous programming model in C#
Async in depth
To return a value from an async method it must be awaited. See the example method call below:
private async Task<System.Net.HttpStatusCode> Execute(String EmailId, String Message)
{
var apiKey = "abcdefghijklmnopqrstuvwxyz1234567890";
var client = new SendGridClient(apiKey);
var from = new EmailAddress("myemail#gmail.com", "Sender");
var subject = "Testing Email";
var to = new EmailAddress(EmailId, "Reciever");
var plainTextContent = "You have recieved this message from me";
var htmlContent = Message + "<br><i>-Message sent by me</i>";
var msg = MailHelper.CreateSingleEmail(from, to, subject, plainTextContent, htmlContent);
var response = await client.SendEmailAsync(msg).ConfigureAwait(false);
return response.StatusCode;
}
private async Task GetStatusCodeExample(String EmailId, String Message)
{
var statusCode = await Execute(EmailId, Message);
}
EDIT:
update your code to use the following along with the above updated Execute method:
protected void BtnSend_Click(object sender, EventArgs e)
{
lblmsg.InnerText = SendMail(txtEmailId.Text.ToString(),
txtMessage.Text.ToString()); //------------
private String SendMail(String EmailId, String Message)
{
var task = Execute(EmailId, Message);
task.Wait();
return ((int)task.Result).ToString();
}
Related
I am trying to send the same automatic email to multiple email addresses but I can't get it to work.
[HttpGet("largeorderemail")]
public IActionResult LargeOrderEmail()
{
try
{
//var bodyString = $"<h3>{msg}</h3><br/><p> Visit the site <a href='{Startup.appSettings.AllowOrigin}/lidarweb'> LiDAR GIS portal.</a></p>";
var bodyString = $"<h3>email body</h3>" +
<br/>" +
var emailService = new Email { To = "info#tel.net" };
var response = emailService.ExecuteLargeOrder(bodyString);
return Ok();
}
catch (Exception e)
{
Log.Error(e);
return NotFound();
}
}
public async Task<Response> ExecuteLargeOrder(string bodyString)
{
var fromAddr = new EmailAddress(from, "Info");
subject = "large order";
var toAddr = new EmailAddress(to, "User");
plainTextContent = "";
htmlContent = bodyString;
var msg = MailHelper.CreateSingleEmail(fromAddr, toAddr, subject, plainTextContent, htmlContent);
var response = await client.SendEmailAsync(msg);
return response;
}
When I send an email to a single address, it works. Like so: var emailService = new Email { To = "info#tel.net" };
but when I try something like this, it doesn't send the email var emailService = new Email { To = "info#tel.net, info#gmail.com" };
I also tried separating the address like so var emailService = new Email { To = "info#tel.net; info#gmail.com" }; but this also doesn't work.
Any suggestions?
Instead of putting Email addresses, try doing this way. Keep all your Email address in Array and try looping through the Array so that you can achieve your goal.
I wrote a function using GetAsync() which works fine, but now i'd like to expand on it using SendAsync() instead [for POSTing and sofourth]; however my SendAsync() version is not working as expected, it returns a 422 unprocessible entity. (no IDE atm; sorry for minor typos)
init
var Client = new HttpClient{
BaseAddress = "https://example.com"
}
Client.DefaultRequestHeaders.UserAgent.ParseAdd("Project/1.0 (blah blah)");
...
Working GetAsync()
public async Task<string> GetResponse(string user, string pass){
var uri = $"/user/login.json?name={user}&password={pass}";
var req = await Client.GetAsync(uri);
return req.Content.Request.Content.ReasStringAsync();
}
non working SendAsync()
public async Task<string> GetResponse(string page, Dictionary<string, string> args){
//assume page = "/user/login.json" and args == {"username", "user"},{"password", "pass"}
try{
var req = new HttpRequestMessage
{
Method = HttpMethod.Get,
RequestUri = new Uri(page),
Content = new FormUrlEncodedContent(args),
}
var response = await Client.SendAsync(req);
if(response.IsSuccessStatusCode){
return await response.Content.ReasStringAsync();
return null;
}
catch{ return null }
}
note: along with the 422, the response still contains json which states "invalid Auth Token!"
What is GetAsync() doing that SendAsync() is not?
Your Send included content in the BODY of a HTTP GET request.
HTTP GET requests should not have a BODY and there are servers that wont process such requests.
Convert the dictionary to a QueryString and include it in the URI.
public async Task<string> GetResponse(string page, Dictionary<string, string> args) {
//assume page = "/user/login.json" and args == {"username", "user"},{"password", "pass"}
try {
QueryString queryString = QueryString.Create(args);
var uri = new Uri(page + queryString.ToString());
var request = new HttpRequestMessage(HttpMethod.Get, uri);
var response = await Client.SendAsync(request);
if(response.IsSuccessStatusCode){
return await response.Content.ReadAsStringAsync();
return string.Empty;
} catch { return string.Empty; }
}
Your code snippets don't show it, but are you sure the second query's URL has
$"/user/login.json?name={user}&password={pass}"
and not
$"/user/login.json"
?
I am using SendGrid, and I want to add one or more category to the email, but the added category hadn't been sent!
This is the code:
internal class Example
{
private static void Main()
{
Execute().Wait();
}
static async Task Execute()
{
//FYI, the following three variables are not real
var apiKey = "SG.XXX";
var fromEmail = "";
var toEmail = "";
var client = new SendGridClient(apiKey);
var from = new EmailAddress(fromEmail);
var subject = "Sending with SendGrid is Fun";
var to = new EmailAddress(toEmail);
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);
msg.AddHeader("category", "cat1"); //This line does nothing!
var response = await client.SendEmailAsync(msg);
}
}
Thanks Kami, I tried your answer and it worked properly.
I replaced this line msg.AddHeader("category", "cat1"); with msg.AddCategory("cat1");
I'm trying to send email from sendgrid as follows-
public static async Task<int> SendEmail(string fromEmail, string toEmail, string emailMessage, string subject)
{
try
{
// Create the email object first, then add the properties.
var myMessage = new SendGridMessage();
// Add the message properties.
myMessage.AddTo(toEmail);
myMessage.From = new MailAddress(fromEmail);
myMessage.Subject = subject;
myMessage.Html = emailMessage;
var username = ConfigurationManager.AppSettings["NetworkUserId"];
var pswd = ConfigurationManager.AppSettings["NetworkUserPwd"];
var domain = ConfigurationManager.AppSettings["HostName"];
// Create credentials, specifying your user name and password.
var credentials = new NetworkCredential(username, pswd, domain);
// Create an Web transport for sending email.
var transportWeb = new Web(credentials);
if (transportWeb != null)
await transportWeb.DeliverAsync(myMessage);
else
{
await Task.FromResult(0);
}
}
catch (System.Exception ex)
{
//throw ex;
}
return 1;
}
Here I'm using async and await, I got mail successfully but I'm expecting return value as 1. I think my debugger hitch into await.
You do not need to await the result of 0, your code should be:
public static async Task<int> SendEmail(string fromEmail, string toEmail, string emailMessage, string subject) {
try {
// Same as your example
if (transportWeb != null)
await transportWeb.DeliverAsync("");
else {
return 0;
}
}
catch (System.Exception ex) {
//throw ex;
}
return 1;
}
I'm new to using async methods and could use some help. Winforms .Net 4.5 program: ReadInputFile loops through each line in a csv file and calls the async method UpdatePOS_Monitor which posts to the API. Everything is working so far (my database is getting the new rows) but I don't know how to exit the application when ReadInputFile is done because it is calling an async method. Or if ReadInputFile will get ahead of itself with this setup? I'm guessing I need to be 'awaiting' somewhere but don't know what to do? Thank you.
private void ReadInputFile()
{
var reader = new StreamReader(File.OpenRead(FilePath + #"\" + FileNameAdd));
while (!reader.EndOfStream)
{
var line = reader.ReadLine();
var values = line.Split(',');
var Newline = new RevenueLine();
Newline.ClubID = values[0];
Newline.Date = values[1];
Newline.Department = values[2];
Newline.Description = values[3];
Newline.Chits = Convert.ToInt32(values[4]);
Newline.Sales = values[5];
UpdatePOS_Monitor(Newline);
}
}
private async void UpdatePOS_Monitor(RevenueLine line)
{
HttpClient client = new HttpClient();
try
{
string json = JsonConvert.SerializeObject(line);
HttpResponseMessage wcfResponse = await client.PostAsync(API_Address, new StringContent(json, Encoding.UTF8, "application/json"));
}
catch
{
}
}
If you're using async/await, the whole chain of methods has to be async, all the way down to the root (e.g., to the UI control event handler). In your case it means that ReadInputFile has to be async, and UpdatePOS_Monitor has to be async Task rather than async void:
// root event handler
private async void button_Click(object s, EventArgs e)
{
await ReadInputFile();
}
private async Task ReadInputFile()
{
var reader = new StreamReader(File.OpenRead(FilePath + #"\" + FileNameAdd));
while (!reader.EndOfStream)
{
var line = await reader.ReadLineAsync();
var values = line.Split(',');
var Newline = new RevenueLine();
Newline.ClubID = values[0];
Newline.Date = values[1];
Newline.Department = values[2];
Newline.Description = values[3];
Newline.Chits = Convert.ToInt32(values[4]);
Newline.Sales = values[5];
await UpdatePOS_Monitor(Newline);
}
}
private async Task UpdatePOS_Monitor(RevenueLine line)
{
using (HttpClient client = new HttpClient())
{
string json = JsonConvert.SerializeObject(line);
HttpResponseMessage wcfResponse = await client.PostAsync(API_Address, new StringContent(json, Encoding.UTF8, "application/json"));
}
}
Note also await reader.ReadLineAsync, await UpdatePOS_Monitor(Newline) and the removal of catch {} inside UpdatePOS_Monitor (it's almost always a bad idea to swallow exceptions like that).