我正在执行定时后台任务以发送电子邮件,并且我想在电子邮件中包含生成的链接。
当我通过控制器中的用户交互发送其他电子邮件时,我正在使用这种小方法来生成链接:
public string BuildUrl(string controller, string action, int id)
{
Uri domain = new Uri(Request.GetDisplayUrl());
return domain.Host + (domain.IsDefaultPort ? "" : ":" + domain.Port) +
$@"/{controller}/{action}/{id}";
}
当然,后台任务对Http上下文一无所知,因此我需要替换链接的域部分,如下所示:
public string BuildUrl(string controller, string action, int id)
{
return aStringPassedInFromSomewhere + $@"/{controller}/{action}/{id}";
}
我正在启动startup.cs ConfigureServices中的后台任务,如下所示:
services.AddHostedService<ProjectTaskNotifications>();
我本来是想从资源文件中获取域名,但是我也可以将其硬编码到任务方法中。
是否可以通过某种方式将这些信息动态传递给后台任务?
更多信息
这是整个后台任务:
internal class ProjectTaskNotifications : IHostedService, IDisposable
{
private readonly ILogger _logger;
private Timer _timer;
private readonly IServiceScopeFactory scopeFactory;
private readonly IMapper auto;
public ProjectTaskNotifications(
ILogger<ProjectTaskNotifications> logger,
IServiceScopeFactory scopeFactory,
IMapper mapper)
{
_logger = logger;
this.scopeFactory = scopeFactory;
auto = mapper;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Timed Background Service is starting.");
_timer = new Timer(DoWork, null, TimeSpan.Zero,
TimeSpan.FromSeconds(30));
return Task.CompletedTask;
}
private void DoWork(object state)
{
_logger.LogInformation("Timed Background Service is working.");
// Connect to the database and cycle through all unsent
// notifications, checking if some of them are due to be sent:
using (var scope = scopeFactory.CreateScope())
{
var db = scope.ServiceProvider.GetRequiredService<MyDbContext>();
List<ProjectTaskNotification> notifications = db.ProjectTaskNotifications
.Include(t => t.Task)
.ThenInclude(o => o.TaskOwner)
.Include(t => t.Task)
.ThenInclude(p => p.Project)
.ThenInclude(o => o.ProjectOwner)
.Where(s => !s.IsSent).ToList();
foreach (var notification in notifications)
{
if (DateTime.UtcNow > notification.Task.DueDate
.AddMinutes(-notification.TimeBefore.TotalMinutes))
{
SendEmail(notification);
notification.Sent = DateTime.UtcNow;
notification.IsSent = true;
}
}
db.UpdateRange(notifications);
db.SaveChanges();
}
}
public Task StopAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("Timed Background Service is stopping.");
_timer?.Change(Timeout.Infinite, 0);
return Task.CompletedTask;
}
public void Dispose()
{
_timer?.Dispose();
}
public void SendEmail(ProjectTaskNotification notification)
{ // Trimmed down for brevity
// Key parts
string toAddr = notification.Task.TaskOwner.Email1;
BodyBuilder bodyBuilder = new BodyBuilder
{
HtmlBody = TaskInfo(auto.Map<ProjectTaskViewModel>(notification.Task))
};
return;
}
public string TaskInfo(ProjectTaskViewModel task)
{ // Trimmed down for brevity
return $@"<p>{BuildUrl("ProjectTasks", "Edit", task.Id)}</p>";
}
public string BuildUrl(string controller, string action, int id)
{
// This is where I need the domain name sent in from somewhere:
return "domain:port" + $@"/{controller}/{action}/{id}";
}
}
答案 0 :(得分:0)
您可以通过构造函数将任何对象传递给IHostedService
提供者。
public ProjectTaskNotifications(IUrlPrefixProvider provider)
{
_urlPrefixProvider = urlPrefixProvider
}
private string BuildUrl(<Your args>)
{
var prefix = _urlPrefixProvider.GetPrefix(<args>);
....
}
在startup.cs中,您可以拥有
services.AddSingleton<IUrlPrefixProvider, MyUrlPrefixProvider>()
services.AddHostedService<ProjectTaskNotifications>();
并让依赖注入负责其余的工作。