Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Bjarne Fyrstenborg 1286 posts 4060 karma points MVP 8x c-trib
    Sep 19, 2018 @ 06:55
    Bjarne Fyrstenborg
    0

    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?

    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);
        }
    }
    

    /Bjarne

  • John Bergman 483 posts 1132 karma points
    Sep 19, 2018 @ 07:04
    John Bergman
    0

    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 :-).

  • Ranjit J. Vaity 66 posts 109 karma points
    Dec 08, 2019 @ 14:02
    Ranjit J. Vaity
    0

    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

  • John Bergman 483 posts 1132 karma points
    Dec 09, 2019 @ 00:54
    John Bergman
    1

    Here is the EnsureUmbracoContext we use

        /// <summary>
    /// Ensure there is an umbraco context for cases where we dont have one
    /// 
    /// Based on:  https://gist.github.com/sniffdk/7600822
    /// 
    /// Other references for creating an UmbracoContext / UmbracoHelper
    ///   https://staheri.com/my-blog/2015/march/custom-examine-indexing-using-umbraco-cache/
    ///   https://our.umbraco.com/forum/umbraco-7/using-umbraco-7/57892-IPublishedContent-and-GatheringNodeData
    /// </summary>
    public static void EnsureUmbracoContext()
    {
      if (UmbracoContext.Current == null)
      {
        var dummyHttpContext = new HttpContextWrapper(new HttpContext(new SimpleWorkerRequest("/", string.Empty, new StringWriter())));  //blah.aspx
        UmbracoContext.EnsureContext(
            dummyHttpContext,
            ApplicationContext.Current,
            new WebSecurity(dummyHttpContext, ApplicationContext.Current),
            UmbracoConfig.For.UmbracoSettings(),
            UrlProviderResolver.Current.Providers,
            false);
      }
    }
    

    And the we call it this way

        EnsureUmbracoContext();
        UmbracoHelper umbracoHelper = new UmbracoHelper(UmbracoContext.Current);
        MembershipHelper membershipHelper = new MembershipHelper(UmbracoContext.Current);
    
  • Bjarne Fyrstenborg 1286 posts 4060 karma points MVP 8x c-trib
    Dec 10, 2019 @ 15:10
    Bjarne Fyrstenborg
    1

    Hi John

    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;
    

    /Bjarne

  • Ranjit J. Vaity 66 posts 109 karma points
    Dec 10, 2019 @ 20:28
    Ranjit J. Vaity
    0

    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:

    RecurringJob.AddOrUpdate<ImportContentHelper>(x => x.ExcuteJob(), Cron.DayInterval(days));
    

    ImportContentHelper.cs as below

    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?

    Please advise.

    Thanks again,

    Ranjit

  • This forum is in read-only mode while we transition to the new forum.

    You can continue this topic on the new forum by tapping the "Continue discussion" link below.

Please Sign in or register to post replies