public override string CreateExpiredJob(Common.Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn)
        {
            if (job == null)
            {
                throw new ArgumentNullException(nameof(job));
            }
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            InvocationData invocationData = InvocationData.Serialize(job);
            PushResponse   response       = Client.Push("jobs", new Entities.Job
            {
                InvocationData = invocationData,
                Arguments      = invocationData.Arguments,
                CreatedOn      = createdAt,
                ExpireOn       = createdAt.Add(expireIn),

                Parameters = parameters.Select(p => new Parameter
                {
                    Name  = p.Key,
                    Value = p.Value
                }).ToArray()
            });

            if (response.StatusCode == HttpStatusCode.OK)
            {
                return(response.Result.name);
            }

            return(string.Empty);
        }
        public override string CreateExpiredJob(Common.Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn)
        {
            if (job == null)
            {
                throw new ArgumentNullException(nameof(job));
            }
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            InvocationData invocationData = InvocationData.Serialize(job);

            Documents.Job entityJob = new Documents.Job
            {
                InvocationData = invocationData,
                Arguments      = invocationData.Arguments,
                CreatedOn      = createdAt,
                ExpireOn       = createdAt.Add(expireIn).ToEpoch(),
                Parameters     = parameters
            };

            IOperationResult <Documents.Job> response = bucket.Insert(entityJob.Id, entityJob);

            if (response.Success)
            {
                return(entityJob.Id);
            }

            return(string.Empty);
        }
        public static NonEscapedString Render(Common.Job job)
        {
            //if (job == null) { return new NonEscapedString("<em>" + Hangfire.Dashboard.Resources.Strings.Common_CannotFindTargetMethod + "</em>"); }

            var type   = Type.GetType("Hangfire.Dashboard.JobMethodCallRenderer,Hangfire.Core");
            var render = type.GetMethod("Render");

            return(render.Invoke(null, new[] { job }) as NonEscapedString);
        }
        public override JobData GetJobData(string jobId)
        {
            if (jobId == null)
            {
                throw new ArgumentNullException(nameof(jobId));
            }

            Uri uri = UriFactory.CreateDocumentUri(Storage.Options.DatabaseName, Storage.Options.CollectionName, jobId);
            Task <DocumentResponse <Documents.Job> > task = Storage.Client.ReadDocumentWithRetriesAsync <Documents.Job>(uri, new RequestOptions {
                PartitionKey = new PartitionKey((int)DocumentTypes.Job)
            });

            task.Wait();

            if (task.Result.Document != null)
            {
                Documents.Job  data           = task.Result;
                InvocationData invocationData = data.InvocationData;
                invocationData.Arguments = data.Arguments;

                Common.Job       job           = null;
                JobLoadException loadException = null;

                try
                {
                    job = invocationData.DeserializeJob();
                }
                catch (JobLoadException ex)
                {
                    loadException = ex;
                }

                return(new JobData
                {
                    Job = job,
                    State = data.StateName,
                    CreatedAt = data.CreatedOn,
                    LoadException = loadException
                });
            }

            return(null);
        }
示例#5
0
        public override JobData GetJobData(string jobId)
        {
            if (jobId == null)
            {
                throw new ArgumentNullException(nameof(jobId));
            }

            Entities.Job data = Storage.Client.CreateDocumentQuery <Entities.Job>(Storage.Collections.JobDocumentCollectionUri, QueryOptions)
                                .Where(j => j.Id == jobId)
                                .AsEnumerable()
                                .FirstOrDefault();

            if (data != null)
            {
                InvocationData invocationData = data.InvocationData;
                invocationData.Arguments = data.Arguments;

                Common.Job       job           = null;
                JobLoadException loadException = null;

                try
                {
                    job = invocationData.Deserialize();
                }
                catch (JobLoadException ex)
                {
                    loadException = ex;
                }

                return(new JobData
                {
                    Job = job,
                    State = data.StateName,
                    CreatedAt = data.CreatedOn,
                    LoadException = loadException
                });
            }

            return(null);
        }
        public override string CreateExpiredJob(Common.Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn)
        {
            if (job == null)
            {
                throw new ArgumentNullException(nameof(job));
            }
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            InvocationData invocationData = InvocationData.SerializeJob(job);

            Documents.Job entityJob = new Documents.Job
            {
                InvocationData = invocationData,
                Arguments      = invocationData.Arguments,
                CreatedOn      = createdAt,
                ExpireOn       = createdAt.Add(expireIn),

                Parameters = parameters.Select(p => new Parameter
                {
                    Name  = p.Key,
                    Value = p.Value
                }).ToArray()
            };

            Task <ResourceResponse <Document> > task = Storage.Client.CreateDocumentWithRetriesAsync(Storage.CollectionUri, entityJob, new RequestOptions {
                PartitionKey = new PartitionKey((int)DocumentTypes.Job)
            });

            task.Wait();

            if (task.Result.StatusCode == HttpStatusCode.Created || task.Result.StatusCode == HttpStatusCode.OK)
            {
                return(entityJob.Id);
            }

            return(string.Empty);
        }
示例#7
0
        public override JobData GetJobData(string jobId)
        {
            if (jobId == null)
            {
                throw new ArgumentNullException(nameof(jobId));
            }

            Task <ItemResponse <Documents.Job> > task = Storage.Container.ReadItemWithRetriesAsync <Documents.Job>(jobId, new PartitionKey((int)DocumentTypes.Job));

            task.Wait();

            if (task.Result.Resource != null)
            {
                Documents.Job  data           = task.Result;
                InvocationData invocationData = data.InvocationData;
                invocationData.Arguments = data.Arguments;

                Common.Job       job           = null;
                JobLoadException loadException = null;

                try
                {
                    job = invocationData.DeserializeJob();
                }
                catch (JobLoadException ex)
                {
                    loadException = ex;
                }

                return(new JobData
                {
                    Job = job,
                    State = data.StateName,
                    CreatedAt = data.CreatedOn,
                    LoadException = loadException
                });
            }

            return(null);
        }
示例#8
0
        public override JobData GetJobData(string jobId)
        {
            if (jobId == null)
            {
                throw new ArgumentNullException(nameof(jobId));
            }

            Uri uri = UriFactory.CreateDocumentUri(Storage.Options.DatabaseName, Storage.Options.CollectionName, jobId);
            Task <DocumentResponse <Documents.Job> > task = Storage.Client.ReadDocumentAsync <Documents.Job>(uri);

            Documents.Job data = task.Result;

            if (data != null)
            {
                InvocationData invocationData = data.InvocationData;
                invocationData.Arguments = data.Arguments;

                Common.Job       job           = null;
                JobLoadException loadException = null;

                try
                {
                    job = invocationData.Deserialize();
                }
                catch (JobLoadException ex)
                {
                    loadException = ex;
                }

                return(new JobData
                {
                    Job = job,
                    State = data.StateName,
                    CreatedAt = data.CreatedOn,
                    LoadException = loadException
                });
            }

            return(null);
        }
        public override JobData GetJobData(string jobId)
        {
            if (jobId == null)
            {
                throw new ArgumentNullException(nameof(jobId));
            }

            IDocumentResult <Documents.Job> result = bucket.GetDocument <Documents.Job>(jobId);

            if (result.Success && result.Content != null)
            {
                Documents.Job  data           = result.Content;
                InvocationData invocationData = data.InvocationData;
                invocationData.Arguments = data.Arguments;

                Common.Job       job           = null;
                JobLoadException loadException = null;

                try
                {
                    job = invocationData.Deserialize();
                }
                catch (JobLoadException ex)
                {
                    loadException = ex;
                }

                return(new JobData
                {
                    Job = job,
                    State = data.StateName,
                    CreatedAt = data.CreatedOn,
                    LoadException = loadException
                });
            }

            return(null);
        }
        public override JobData GetJobData(string jobId)
        {
            if (jobId == null)
            {
                throw new ArgumentNullException(nameof(jobId));
            }

            FirebaseResponse response = Client.Get($"jobs/{jobId}");

            if (response.StatusCode == HttpStatusCode.OK && !response.IsNull())
            {
                Entities.Job   data           = response.ResultAs <Entities.Job>();
                InvocationData invocationData = data.InvocationData;
                invocationData.Arguments = data.Arguments;

                Common.Job       job           = null;
                JobLoadException loadException = null;

                try
                {
                    job = invocationData.Deserialize();
                }
                catch (JobLoadException ex)
                {
                    loadException = ex;
                }

                return(new JobData
                {
                    Job = job,
                    State = data.StateName,
                    CreatedAt = data.CreatedOn,
                    LoadException = loadException
                });
            }

            return(null);
        }
示例#11
0
        public override string CreateExpiredJob(Common.Job job, IDictionary <string, string> parameters, DateTime createdAt, TimeSpan expireIn)
        {
            if (job == null)
            {
                throw new ArgumentNullException(nameof(job));
            }
            if (parameters == null)
            {
                throw new ArgumentNullException(nameof(parameters));
            }

            InvocationData invocationData = InvocationData.Serialize(job);

            Entities.Job entityJob = new Entities.Job
            {
                InvocationData = invocationData,
                Arguments      = invocationData.Arguments,
                CreatedOn      = createdAt,
                ExpireOn       = createdAt.Add(expireIn),

                Parameters = parameters.Select(p => new Parameter
                {
                    Name  = p.Key,
                    Value = p.Value
                }).ToArray()
            };

            ResourceResponse <Document> response = Storage.Client.CreateDocumentWithRetriesAsync(Storage.Collections.JobDocumentCollectionUri, entityJob).GetAwaiter().GetResult();

            if (response.StatusCode == HttpStatusCode.Created || response.StatusCode == HttpStatusCode.OK)
            {
                return(entityJob.Id);
            }

            return(string.Empty);
        }
示例#12
0
        private static void CreateManagement(ManagementPagesOptions options = null)
        {
            #region 翻译
            var resourceManager        = Hangfire.Dashboard.Resources.Strings.ResourceManager;
            var resourceManField       = typeof(Hangfire.Dashboard.Resources.Strings).GetField("resourceMan", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
            var customHangfireLanguage = new CustomHangfireLanguage(resourceManager, options.translateFunc, options.culture);
            resourceManField.SetValue(null, customHangfireLanguage /*_customHangfireLanguage*/);
            JobHistoryRenderer.Register(customHangfireLanguage);
            //翻译时间脚本
            var jsPath = Hangfire.Dashboard.DashboardRoutes.Routes.Contains("/js[0-9]+") ? "/js[0-9]+" : "/js[0-9]{3}";
            //DashboardRoutes.Routes.Append(jsPath, new DynamicJsDispatcher());
            DashboardRoutes.Routes.Append(jsPath, new EmbeddedResourceDispatcher("application/javascript", Assembly.GetExecutingAssembly(), $"{typeof(GlobalConfigurationExtension).Namespace}.Content.momentLocale.js"));
            //
            #endregion 翻译
            //Cron最近5次运行时间
            //cron?cron=0+0+0+*+*+%3F+
            DashboardRoutes.Routes.Add("/cron", new CommandDispatcher(async context =>
            {
                var cron = context.Request.GetQuery("cron");
                //var result = CronExpressionDescriptor.ExpressionDescriptor.GetDescription(cron, new Options
                //{
                //    ThrowExceptionOnParseError = false,
                //    Verbose = false,
                //    DayOfWeekStartIndexZero = true,
                //    Locale = (locale ?? "en-US")
                //});
                //var cronDescription = Hangfire.Cron.GetDescription(cron);
                var cronDescription = CronExpressionDescriptor.ExpressionDescriptor.GetDescription(cron);
                var cronSchedule    = Cronos.CronExpression.Parse(cron);
                var example         = cronSchedule.GetOccurrences(System.DateTime.UtcNow, System.DateTime.Now.AddYears(5)).Take(5).ToArray();
                //var cronSchedule = NCrontab.CrontabSchedule.Parse(cron);
                //var example = cronSchedule.GetNextOccurrences(System.DateTime.UtcNow, System.DateTime.Now.AddYears(5)).Take(5).ToArray();
                var str = Newtonsoft.Json.JsonConvert.SerializeObject(new
                {
                    Description = cronDescription,
                    Example     = example
                });
                await context.Response.WriteAsync(str);
                return(true);
            }));
            var pages = options.GetPages();
            #region 任务
            ManagementSidebarMenu.Items.Clear();
            foreach (var pageInfo in pages)
            {
                //添加命令
                //ManagementBasePage.AddCommands(pageInfo.Queue);
                //添加菜单连接
                var path = $"{ManagementPage.UrlRoute}/{pageInfo.Title.ToBase64Url()}";
                ManagementSidebarMenu.Items.Add(p => new MenuItem(pageInfo.Title, path)
                {
                    Active = p.RequestPath.StartsWith(path),
                    Metric = new DashboardMetric(
                        "metrics:count",
                        "Metrics_Count",
                        page => new Metric(pageInfo.Metadatas.Length)
                    {
                        //Style = pageInfo.Metadatas.Length > 0 ? MetricStyle.Info : MetricStyle.Default,
                        //Highlighted = pageInfo.Metadatas.Length > 0
                    })
                });
                ////添加页面
                DashboardRoutes.Routes.AddRazorPage(path, x => new ManagementBasePage(pageInfo.Title, pageInfo.Title, pageInfo.Metadatas));
            }
            #endregion 任务

            //暂停取消功能
            GlobalJobFilters.Filters.Add(new PauseStateAttribute());
            DashboardRoutes.Routes.AddRazorPage(ManagementPage.UrlRoute, x => new ManagementPage());
            //DashboardRoutes.Routes.AddRazorPage("/recurring/addJobs", x => new ManagementPage());

            // can't use the method of Hangfire.Console as it's usage overrides any similar usage here. Thus
            // we have to add our own endpoint to load it and call it from our code. Actually is a lot less work
            //DashboardRoutes.Routes.Add("/jsm", new EmbeddedResourceDispatcher("application/javascript", Assembly.GetExecutingAssembly(), $"{typeof(GlobalConfigurationExtension).Namespace}.Content.management.js"));
            //DashboardRoutes.Routes.Add("/jsm", new CombinedResourceDispatcher("application/javascript", Assembly.GetExecutingAssembly(), $"{typeof(GlobalConfigurationExtension).Namespace}.Content", new[] { "management.js", "cron.js" }));
            DashboardRoutes.Routes.Append(jsPath, new CombinedResourceDispatcher("application/javascript", Assembly.GetExecutingAssembly(), $"{typeof(GlobalConfigurationExtension).Namespace}.Content", new[] { "management.js", "cron.js" }));

            //NavigationMenu.Items.Add(page => new MenuItem(ManagementPage.Title, page.Url.To(ManagementPage.UrlRoute))
            //{
            //    Active = page.RequestPath.StartsWith(ManagementPage.UrlRoute)
            //});

            //执行暂停命令
            DashboardRoutes.Routes.AddBatchCommand("/recurring/pause", (context, jobId) =>
            {
                if (context.IsReadOnly)
                {
                    return;
                }
                using (var connection = context.Storage.GetConnection())
                {
                    connection.SetPauseState(jobId, true);
                }
            });
            //执行恢复命令
            DashboardRoutes.Routes.AddBatchCommand("/recurring/repeat", (context, jobId) =>
            {
                if (context.IsReadOnly)
                {
                    return;
                }
                using (var connection = context.Storage.GetConnection())
                {
                    connection.SetPauseState(jobId, false);
                }
            });
            //执行添加任务
            DashboardRoutes.Routes.AddCommand($"{ManagementPage.UrlRoute}/addJob", context =>
            {
                if (context.IsReadOnly)
                {
                    return(false);
                }
                if (context.Request.Method == "POST")
                {
                    //Hangfire官方在Owin模式获取参数会有问题,只能获取一次,第二次会是空值
                    var getFormValue = new Func <string, IList <string> >(key =>
                    {
                        ////Owin模式
                        //var environment = context.GetOwinEnvironment();
                        //var _context = new Microsoft.Owin.OwinContext(environment);
                        //var form = _context.Request.ReadFormSafeAsync().Result;
                        //var r =  form.GetValues(_key);
                        ////aspnet模式
                        //var r = context.Request.GetFormValuesAsync(key)?.Result;
                        //return r.Select(f => string.IsNullOrWhiteSpace(f) ? null : f).ToArray();
                        //通用模式
                        IList <string> getValue(string _key)
                        {
#if NETFULL
                            //Owin模式
                            var environment = context.GetOwinEnvironment();
                            var _context    = new Microsoft.Owin.OwinContext(environment);
                            var form        = _context.Request?.ReadFormAsync()?.Result;
                            return(form?.GetValues(_key));
#else
                            return(context.Request.GetFormValuesAsync(_key)?.Result);
#endif
                        }
                        var r = getValue(key);
                        return(r.Select(f => string.IsNullOrWhiteSpace(f) ? null : f).ToArray());
                    });

                    var jobtype     = getFormValue("type")?.FirstOrDefault();
                    var id          = getFormValue("id")?.FirstOrDefault();
                    var jobMetadata = pages.SelectMany(f => f.Metadatas.Where(fff => fff.GetId() == id)).FirstOrDefault();
                    var par         = new List <object>();

                    foreach (var parameterInfo in jobMetadata.Parameters)
                    {
                        if (parameterInfo.ParameterType == typeof(Server.PerformContext) || parameterInfo.ParameterType == typeof(IJobCancellationToken))
                        {
                            par.Add(null);
                            continue;
                        }
                        ;

                        var variable = $"{id}_{parameterInfo.Name}";
                        if (parameterInfo.ParameterType == typeof(DateTime))
                        {
                            variable = $"{variable}_datetimepicker";
                        }

                        var t = getFormValue(variable);

                        object item   = null;
                        var formInput = t?.FirstOrDefault();
                        if (parameterInfo.ParameterType == typeof(string) || parameterInfo.ParameterType == typeof(Uri) || parameterInfo.ParameterType.IsEnum)
                        {
                            item = formInput;
                        }
                        else if (parameterInfo.ParameterType == typeof(int))
                        {
                            if (formInput != null)
                            {
                                item = int.Parse(formInput);
                            }
                        }
                        else if (parameterInfo.ParameterType == typeof(DateTime))
                        {
                            item = formInput == null ? DateTime.MinValue : DateTime.Parse(formInput);
                        }
                        else if (parameterInfo.ParameterType == typeof(bool))
                        {
                            item = formInput == "on";
                        }
                        else
                        {
                            throw new NotImplementedException();
                        }

                        par.Add(item);
                    }


                    var job    = new Common.Job(jobMetadata.Type, jobMetadata.MethodInfo, par.ToArray());
                    var client = new BackgroundJobClient(context.Storage);
                    switch (jobtype)
                    {
                    case "CronExpression":
                        {
                            var manager = new RecurringJobManager(context.Storage);
                            try
                            {
                                var queue       = getFormValue($"{id}_sys_queue")?.FirstOrDefault();
                                var timeZone    = getFormValue($"{id}_sys_timeZone")?.FirstOrDefault() ?? "Utc";
                                var displayName = getFormValue($"{id}_sys_displayName")?.FirstOrDefault();

                                var jobQueue       = (queue?.Trim().Replace("-", "_").Replace(" ", "_") ?? jobMetadata.Queue)?.ToLower();
                                var jobTimeZone    = TimeZoneInfo.FindSystemTimeZoneById(timeZone?.Trim()) ?? TimeZoneInfo.Utc;
                                var jobDisplayName = string.IsNullOrWhiteSpace(displayName) ? jobMetadata.DisplayName : displayName;

                                var schedule = getFormValue("schedule")?.FirstOrDefault();
                                var cron     = getFormValue($"{id}_sys_cron")?.FirstOrDefault();

                                if (string.IsNullOrWhiteSpace(schedule ?? cron))
                                {
                                    throw new Exception("请填写 Cron 表达式");
                                }
                                manager.AddOrUpdate(jobDisplayName, job, schedule ?? cron, jobTimeZone, jobQueue);
                            }
                            catch (Exception)
                            {
                                return(false);
                            }
                            return(true);
                            //break;
                        }

                    case "ScheduleDateTime":
                        {
                            var datetime = getFormValue($"{id}_sys_datetime")?.FirstOrDefault();
                            if (string.IsNullOrWhiteSpace(datetime))
                            {
                                //context.Response.StatusCode = 400;
                                ////Hangfire.Dashboard.AspNetCoreDashboardResponse
                                context.Response.WriteAsync("请填写 执行时间 表达式");
                                throw new Exception("请填写 执行时间 表达式");
                            }
                            var jobId = client.Create(job, new States.ScheduledState(DateTime.Parse(datetime).ToUniversalTime()));    //Queue
                            return(jobId != string.Empty);
                            //break;
                        }

                    case "ScheduleTimeSpan":
                        {
                            var schedule = getFormValue("schedule")?.FirstOrDefault();
                            var timeSpan = getFormValue($"{id}_sys_timespan")?.FirstOrDefault();
                            if (string.IsNullOrWhiteSpace(schedule ?? timeSpan))
                            {
                                throw new Exception("请填写 延迟时间 表达式");
                            }
                            var jobId = client.Create(job, new States.ScheduledState(TimeSpan.Parse(schedule ?? timeSpan)));    //Queue
                            return(jobId != string.Empty);
                            //break;
                        }
                    //case "ContinueWith":
                    //    {
                    //        var parentId = getValue("{id}_sys_parentId")?.FirstOrDefault();
                    //        var optionsStr = getValue($"{id}_sys_JobContinuationOptions")?.FirstOrDefault();

                    //        var jobContinuationOptions = JobContinuationOptions.OnlyOnSucceededState;
                    //        Enum.TryParse<JobContinuationOptions>(optionsStr, out jobContinuationOptions);
                    //        var jobId = client.Create(job, new States.AwaitingState(parentId, null, jobContinuationOptions));
                    //        return jobId != string.Empty;
                    //        //break;
                    //    }
                    case "Enqueue":
                    default:
                        {
                            var queue    = getFormValue($"{id}_sys_queue")?.FirstOrDefault();
                            var jobQueue = (queue?.Trim().Replace("-", "_").Replace(" ", "_") ?? jobMetadata.Queue)?.ToLower();
                            var jobId    = client.Create(job, new States.EnqueuedState(jobQueue));
                            return(jobId != string.Empty);
                            //break;
                        }
                        //break;
                    }

                    /*
                     * EnqueuedState
                     * Queue
                     * ScheduledState
                     * AddOrUpdate
                     * DisplayName
                     * TimeZone
                     * Queue
                     * ContinueWith
                     * parentId
                     * jobContinuationOptions
                     */



                    //if (!string.IsNullOrEmpty(schedule))
                    //{
                    //    var minutes = int.Parse(schedule);
                    //    return client.Create(job, new ScheduledState(new TimeSpan(0, 0, minutes, 0))) != string.Empty;
                    //}
                    //else if (!string.IsNullOrEmpty(cron))
                    //{
                    //    var manager = new RecurringJobManager(context.Storage);
                    //    try
                    //    {
                    //        manager.AddOrUpdate(jobMetadata.DisplayName, job, cron, TimeZoneInfo.Utc, queue);
                    //    }
                    //    catch (Exception)
                    //    {
                    //        return false;
                    //    }
                    //    return true;
                    //}
                }
                return(false);
            });
            //替换页面
            if (options.OverrideDefaultHangfirePages)
            {
                var type = Type.GetType("Hangfire.Dashboard.RazorPageDispatcher," + typeof(IGlobalConfiguration).Assembly.FullName);
                if (type != null)
                {
                    object obj        = Activator.CreateInstance(type, new object[] { new Func <System.Text.RegularExpressions.Match, RazorPage>(x => new Hangfire.Dashboard.Management.Pages.RecurringJobsPage()) });
                    var    dispatcher = obj as IDashboardDispatcher;//new RazorPageDispatcher( )
                    Hangfire.Dashboard.DashboardRoutes.Routes.Replace("/recurring", dispatcher);

                    object obj2        = Activator.CreateInstance(type, new object[] { new Func <System.Text.RegularExpressions.Match, RazorPage>(x => new Hangfire.Dashboard.Management.Pages.JobDetailsPage(x.Groups["JobId"].Value)) });
                    var    dispatcher2 = obj2 as IDashboardDispatcher;//new RazorPageDispatcher( )
                    Hangfire.Dashboard.DashboardRoutes.Routes.Replace("/jobs/details/(?<JobId>.+)", dispatcher2);

                    object obj3        = Activator.CreateInstance(type, new object[] { new Func <System.Text.RegularExpressions.Match, RazorPage>(x => new Hangfire.Dashboard.Management.Pages.RetriesPage()) });
                    var    dispatcher3 = obj3 as IDashboardDispatcher;//new RazorPageDispatcher( )
                    Hangfire.Dashboard.DashboardRoutes.Routes.Replace("/retries", dispatcher3);

                    object obj4        = Activator.CreateInstance(type, new object[] { new Func <System.Text.RegularExpressions.Match, RazorPage>(x => new Hangfire.Dashboard.Management.Pages.SucceededJobs()) });
                    var    dispatcher4 = obj4 as IDashboardDispatcher;//new RazorPageDispatcher( )
                    Hangfire.Dashboard.DashboardRoutes.Routes.Replace("/jobs/succeeded", dispatcher4);
                }
            }
        }