I have a Hangfire background task to export some data from Umbraco daily. It seems Hangfire needs to have a parameter constructor to execute the method/task in this class.
It works with the following, when using ContextHelper.EnsureUmbracoContext(), but maybe there is a better way to handle this?
public class ExportService
{
private readonly ApplicationContext _applicationContext;
private readonly UmbracoContext _umbracoContext;
private readonly ILogger _logger;
//public GeckoExportService() : this(UmbracoContext.Current)
//{
//}
// Hangfire needs a parameterless constructor
public ExportService()
{
_umbracoContext = ContextHelper.EnsureUmbracoContext();
}
public ExportService(UmbracoContext umbracoContext)
{
_umbracoContext = umbracoContext ?? throw new ArgumentNullException("umbracoContext");
_applicationContext = _umbracoContext.Application;
_logger = _applicationContext.ProfilingLogger.Logger;
}
public void ExportData()
{
}
}
...
public static class ContextHelper
{
public static UmbracoContext EnsureUmbracoContext()
{
if (UmbracoContext.Current != null)
return UmbracoContext.Current;
var dummyHttpContext = new HttpContextWrapper(new HttpContext(new SimpleWorkerRequest("/", string.Empty, new StringWriter())));
return UmbracoContext.EnsureContext(dummyHttpContext,
ApplicationContext.Current,
new WebSecurity(dummyHttpContext, ApplicationContext.Current),
UmbracoConfig.For.UmbracoSettings(),
UrlProviderResolver.Current.Providers,
false);
}
}
and then in Umbraco then following Hangfire configuration:
public class UmbracoStandardOwinStartup : UmbracoDefaultOwinStartup
{
public override void Configuration(IAppBuilder app)
{
// Ensure the default options are configured
base.Configuration(app);
app.UseCookieAuthentication(new CookieAuthenticationOptions
{
AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
LoginPath = new PathString("/")
});
// Configure the database where Hangfire is going to create its tables
var options = new SqlServerStorageOptions { PrepareSchemaIfNecessary = true };
var connectionString = ApplicationContext.Current.DatabaseContext.ConnectionString;
GlobalConfiguration.Configuration.UseSqlServerStorage(connectionString, options);
// Configure Hangfire dashboard
var dashboardOptions = new DashboardOptions { Authorization = new[] { new UmbracoAuthorizationFilter() } };
app.UseHangfireDashboard("/hangfire", dashboardOptions);
// Create a default Hangfire server
app.UseHangfireServer();
// Schedule jobs
var scheduler = new ScheduleHangfireJobs();
scheduler.ExportData();
}
}
public class ScheduleHangfireJobs
{
RecurringJobManager manager = new RecurringJobManager();
[DisableConcurrentExecution(timeoutInSeconds: 60)]
[AutomaticRetry(Attempts = 3)]
public void ExportData()
{
string timer = "00 23 * * *";
var service = new ExportService(UmbracoContext.Current);
manager.AddOrUpdate("Fetch Data", Job.FromExpression(() => service.ExportData()), timer);
}
}
We do something similar. Instead of determining how to get the umbraco context inside of the hangfire task, I actually wrote it as a "maintenance" page in the CMS, then the background task simply calls the web page to do the work. Made implementation a breeze :-).
If you already have created an instance of UmbracoHelper you don't need to create an instance of MembershipHelper, instead just access it through MembershipHelper property.
UmbracoHelper umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
MembershipHelper membershipHelper = umbracoHelper.MembershipHelper;
public class ImportContentHelper
{
private readonly IContentImportService _contentImportService = null;
public ImportContentHelper()
{
_contentImportService = new ContentImportService();
}
public void ExcuteJob()
{
.....
}
}
Also I have Bootstrapper.cs where exists building of IOC container using Autofac and I registering controllers, services and UmbracoContext as well.
I tried registering ImportContentHelper and IContentImportService/ContentImportService to the container but while ImportContentHelper ctor is called, it fails to inject an instantiated object of the IContentImportService service.
I somehow do not agree the new keyword while i instantiate the service object. Is there any efficient way to do this or am I missing something?
Access UmbracoContext in Hangfire
I have a Hangfire background task to export some data from Umbraco daily. It seems Hangfire needs to have a parameter constructor to execute the method/task in this class.
It works with the following, when using
ContextHelper.EnsureUmbracoContext()
, but maybe there is a better way to handle this?...
and then in Umbraco then following Hangfire configuration:
/Bjarne
Hey Bjarne,
We do something similar. Instead of determining how to get the umbraco context inside of the hangfire task, I actually wrote it as a "maintenance" page in the CMS, then the background task simply calls the web page to do the work. Made implementation a breeze :-).
Hello John,
Can you please point to some code snippet or example page that you might have shared?
Thank you!
@Bjarne Thank you too for sharing....
Regards, Ranjit
Here is the EnsureUmbracoContext we use
And the we call it this way
Hi John
If you already have created an instance of
UmbracoHelper
you don't need to create an instance ofMembershipHelper
, instead just access it throughMembershipHelper
property./Bjarne
Hello John / Bjarne,
Thank you very much for replies. This works like charm! :)
I had to say, curiosity remain about Hangfire and Autofac working together.
Say in my project have I have a derived class from UmbracoDefaultOwinStartup where I register all Recurring Jobs as below:
ImportContentHelper.cs as below
Also I have Bootstrapper.cs where exists building of IOC container using Autofac and I registering controllers, services and UmbracoContext as well.
I tried registering ImportContentHelper and IContentImportService/ContentImportService to the container but while ImportContentHelper ctor is called, it fails to inject an instantiated object of the IContentImportService service.
I somehow do not agree the new keyword while i instantiate the service object. Is there any efficient way to do this or am I missing something?
Please advise.
Thanks again,
Ranjit
is working on a reply...