Is there a way to hook into the WebJobs function execution so we can have a scope per function? Something like this:
kernel.Bind<MyDbContext>().ToSelf().InWebJobFunctionScope();
I would like to use the InScope()
from Ninject, but I don't know where I can find something similar to the static HttpContext.Current
but for WebJob currently running.
I know that this is an old one, but I had the same dramas. Since a more recent version of web jobs you can use instances and instance methods, and pass in custom IJobActivator instances. It's surprisingly easy.
It works perfectly with Ninject. I haven't seen any Ninject examples, so ...
public class MyJobActivator : IJobActivator
{
protected readonly IKernel _kernel;
public MyJobActivator(IKernel kernel)
{
_kernel = kernel;
}
public T CreateInstance<T>()
{
return _kernel.Get<T>();
}
}
public class MyBindings : NinjectModule
{
public override void Load()
{
Bind(typeof(DbContext)).To(typeof(MyEntities));
}
}
class Program
{
static void Main()
{
using (IKernel kernel = new StandardKernel(new MyBindings()))
{
var jobHostConfiguration = new JobHostConfiguration
{
JobActivator = new MyJobActivator(kernel)
};
var host = new JobHost(jobHostConfiguration);
// The following code will invoke a function called ManualTrigger and
// pass in data (value in this case) to the function
host.Call(typeof(Reminders).GetMethod("ManualTrigger"), new { value = 20 });
}
}
}
public class Reminders
{
private readonly IMyService _myService;
public Reminders(IMyService myService)
{
_myService = myService;
}
// This function will be triggered based on the schedule you have set for this WebJob
// This function will enqueue a message on an Azure Queue called queue
[NoAutomaticTrigger]
public async Task ManualTrigger(TextWriter log, int value, TextWriter logger)
{
try
{
// process the notification request
await _myService.FindAndSendReminders();
await _myService.SaveChangesAsync();
}
catch (Exception e)
{
logger.WriteLine(e.Message);
Console.WriteLine(e.Message);
throw;
}
}
}
EDIT: In addition to the above I've seen recently learned that you may not need to use the host.Call(typeof(Reminders).GetMethod("ManualTrigger"), at least for continuous web jobs.
You simply make your Functions class non static and add a constructor for injection, and then make your processing method non static. This is Illustrated below.
public class Program
{
static void Main()
{
using (IKernel kernel = new StandardKernel(new MyBindings()))
{
var jobHostConfiguration = new JobHostConfiguration
{
JobActivator = new MyJobActivator(kernel)
};
var host = new JobHost(jobHostConfiguration);
// The following code ensures that the WebJob will be running continuously
host.RunAndBlock();
}
}
}
public class Functions
{
private readonly IMyService _myService;
public Functions(IMyService myService)
{
_myService = myService;
}
public async Task ProcessReminders([QueueTrigger("reminder-requests")] string notificationMessage, TextWriter logger)
{
try
{
// process the notification request
await _myService.FindAndSendReminders();
await _myService.SaveChangesAsync();
}
catch (Exception e)
{
logger.WriteLine(e.Message);
Console.WriteLine(e.Message);
throw;
}
}
}
I adapted my original code from an article I found for Autofac
http://www.jerriepelser.com/blog/dedependency-injection-with-autofac-and-webjobs
See also
Dependency injection using Azure WebJobs SDK?
And for continuous webjobs
http://www.ryansouthgate.com/2016/05/10/azure-webjobs-and-dependency-injection/
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With