Asp.Net 核心创建一个控制器来使用 SendGrid 发送电子邮件
Asp.Net Core create a controller to send emails using SendGrid
我正在尝试按照这个 https://www.ryadel.com/en/asp-net-core-send-email-messages-sendgrid-api/ 教程
创建一个控制器
我已经添加了除控制器之外的所有内容。我在控制器中的代码是这样的
public class SendGridController : BaseApiController
{
private readonly IEmailSender _emailSender;
public SendGridController(IEmailSender emailSender)
{
_emailSender = emailSender;
}
[HttpPost]
[ProducesResponseType(typeof(string), (int)HttpStatusCode.OK)]
[ProducesResponseType(typeof(string), (int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
[ProducesResponseType(typeof(string), (int)HttpStatusCode.InternalServerError)]
public async Task<ActionResult> SendEmail() {
await _emailSender.SendEmailAsync("test@mail.com", "subject", "something");
return Ok(await _emailSender.SendEmailAsync("test@mail.com", "subject", "something"));
}
}
但我收到以下错误
Argument 1: cannot convert from 'void' to 'object'
我希望能够看到来自发送网格的响应,无论它是否已发送。
这是 SendGridEmailSender class:
public class SendGridEmailSender : IEmailSender
{
public SendGridEmailSender(
IOptions<SendGridEmailSenderOptions> options
)
{
this.Options = options.Value;
}
public SendGridEmailSenderOptions Options { get; set; }
public async Task SendEmailAsync(
string email,
string subject,
string message)
{
await Execute(Options.ApiKey, subject, message, email);
}
private async Task<Response> Execute(
string apiKey,
string subject,
string message,
string email)
{
var client = new SendGridClient(apiKey);
var msg = new SendGridMessage()
{
From = new EmailAddress(Options.SenderEmail, Options.SenderName),
Subject = subject,
PlainTextContent = message,
HtmlContent = message
};
msg.AddTo(new EmailAddress(email));
// disable tracking settings
// ref.: https://sendgrid.com/docs/User_Guide/Settings/tracking.html
msg.SetClickTracking(false, false);
msg.SetOpenTracking(false);
msg.SetGoogleAnalytics(false);
msg.SetSubscriptionTracking(false);
return await client.SendEmailAsync(msg);
}
}
您没有 returning 您拥有的 private
方法的结果:
await Execute(Options.ApiKey, subject, message, email);
所以,你需要return结果
public async Task SendEmailAsync(
string email,
string subject,
string message)
{
result = await Execute(Options.ApiKey, subject, message, email);
// do some checks with result
}
如果您需要在您的控制器代码中检查结果,这将更加棘手,因为 IEmailSender
的签名不提供通用任务对象,您需要手动将其转换 (不推荐)。您可以简单地假设在方法完成后发送成功(因为在其他情况下您会得到异常):
public async Task<ActionResult> SendEmail() {
await _emailSender.SendEmailAsync("test@mail.com", "subject", "something");
// email was sent, no exception
return Ok();
}
如果您需要该方法的响应,您可以使用 _emailSender.SendEmailAsync("test@mail.com", "subject", "something")
执行类似 的操作,而无需使用 await
构造(仍然不推荐这种方法):
/// <summary>
/// Casts a <see cref="Task"/> to a <see cref="Task{TResult}"/>.
/// This method will throw an <see cref="InvalidCastException"/> if the specified task
/// returns a value which is not identity-convertible to <typeparamref name="T"/>.
/// </summary>
public static async Task<T> Cast<T>(this Task task)
{
if (task == null)
throw new ArgumentNullException(nameof(task));
if (!task.GetType().IsGenericType || task.GetType().GetGenericTypeDefinition() != typeof(Task<>))
throw new ArgumentException("An argument of type 'System.Threading.Tasks.Task`1' was expected");
await task.ConfigureAwait(false);
object result = task.GetType().GetProperty(nameof(Task<object>.Result)).GetValue(task);
return (T)result;
}
我正在尝试按照这个 https://www.ryadel.com/en/asp-net-core-send-email-messages-sendgrid-api/ 教程
创建一个控制器我已经添加了除控制器之外的所有内容。我在控制器中的代码是这样的
public class SendGridController : BaseApiController
{
private readonly IEmailSender _emailSender;
public SendGridController(IEmailSender emailSender)
{
_emailSender = emailSender;
}
[HttpPost]
[ProducesResponseType(typeof(string), (int)HttpStatusCode.OK)]
[ProducesResponseType(typeof(string), (int)HttpStatusCode.BadRequest)]
[ProducesResponseType((int)HttpStatusCode.Unauthorized)]
[ProducesResponseType(typeof(string), (int)HttpStatusCode.InternalServerError)]
public async Task<ActionResult> SendEmail() {
await _emailSender.SendEmailAsync("test@mail.com", "subject", "something");
return Ok(await _emailSender.SendEmailAsync("test@mail.com", "subject", "something"));
}
}
但我收到以下错误
Argument 1: cannot convert from 'void' to 'object'
我希望能够看到来自发送网格的响应,无论它是否已发送。
这是 SendGridEmailSender class:
public class SendGridEmailSender : IEmailSender
{
public SendGridEmailSender(
IOptions<SendGridEmailSenderOptions> options
)
{
this.Options = options.Value;
}
public SendGridEmailSenderOptions Options { get; set; }
public async Task SendEmailAsync(
string email,
string subject,
string message)
{
await Execute(Options.ApiKey, subject, message, email);
}
private async Task<Response> Execute(
string apiKey,
string subject,
string message,
string email)
{
var client = new SendGridClient(apiKey);
var msg = new SendGridMessage()
{
From = new EmailAddress(Options.SenderEmail, Options.SenderName),
Subject = subject,
PlainTextContent = message,
HtmlContent = message
};
msg.AddTo(new EmailAddress(email));
// disable tracking settings
// ref.: https://sendgrid.com/docs/User_Guide/Settings/tracking.html
msg.SetClickTracking(false, false);
msg.SetOpenTracking(false);
msg.SetGoogleAnalytics(false);
msg.SetSubscriptionTracking(false);
return await client.SendEmailAsync(msg);
}
}
您没有 returning 您拥有的 private
方法的结果:
await Execute(Options.ApiKey, subject, message, email);
所以,你需要return结果
public async Task SendEmailAsync(
string email,
string subject,
string message)
{
result = await Execute(Options.ApiKey, subject, message, email);
// do some checks with result
}
如果您需要在您的控制器代码中检查结果,这将更加棘手,因为 IEmailSender
的签名不提供通用任务对象,您需要手动将其转换 (不推荐)。您可以简单地假设在方法完成后发送成功(因为在其他情况下您会得到异常):
public async Task<ActionResult> SendEmail() {
await _emailSender.SendEmailAsync("test@mail.com", "subject", "something");
// email was sent, no exception
return Ok();
}
如果您需要该方法的响应,您可以使用 _emailSender.SendEmailAsync("test@mail.com", "subject", "something")
执行类似 await
构造(仍然不推荐这种方法):
/// <summary> /// Casts a <see cref="Task"/> to a <see cref="Task{TResult}"/>. /// This method will throw an <see cref="InvalidCastException"/> if the specified task /// returns a value which is not identity-convertible to <typeparamref name="T"/>. /// </summary> public static async Task<T> Cast<T>(this Task task) { if (task == null) throw new ArgumentNullException(nameof(task)); if (!task.GetType().IsGenericType || task.GetType().GetGenericTypeDefinition() != typeof(Task<>)) throw new ArgumentException("An argument of type 'System.Threading.Tasks.Task`1' was expected"); await task.ConfigureAwait(false); object result = task.GetType().GetProperty(nameof(Task<object>.Result)).GetValue(task); return (T)result; }