Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ public class RecurringJobAttribute : Attribute
/// If false it will be deleted automatically.
/// </summary>
public bool Enabled { get; set; } = true;

public List<object> Arguments { get; set; }

/// <summary>
/// Initializes a new instance of the <see cref="RecurringJobAttribute"/>
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public interface IRecurringJobRegistry
/// <param name="cron">Cron expressions</param>
/// <param name="timeZone"><see cref="TimeZoneInfo"/></param>
/// <param name="queue">Queue name</param>
void Register(string recurringJobId, MethodInfo method, string cron, TimeZoneInfo timeZone, string queue);
void Register(string recurringJobId, MethodInfo method, string cron, TimeZoneInfo timeZone, string queue, List<object> arguments);

}
}
32 changes: 29 additions & 3 deletions src/Hangfire.RecurringJobAdmin/Core/RecurringJobRegistry.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ namespace Hangfire.RecurringJobAdmin.Core
/// </summary>
public class RecurringJobRegistry : IRecurringJobRegistry
{

/// <summary>
/// Register RecurringJob via <see cref="MethodInfo"/>.
/// </summary>
Expand All @@ -21,7 +21,7 @@ public class RecurringJobRegistry : IRecurringJobRegistry
/// <param name="cron">Cron expressions</param>
/// <param name="timeZone"><see cref="TimeZoneInfo"/></param>
/// <param name="queue">Queue name</param>
public void Register(string recurringJobId, MethodInfo method, string cron, TimeZoneInfo timeZone, string queue)
public void Register(string recurringJobId, MethodInfo method, string cron, TimeZoneInfo timeZone, string queue, List<object> arguments)
{
if (recurringJobId == null) throw new ArgumentNullException(nameof(recurringJobId));
if (method == null) throw new ArgumentNullException(nameof(method));
Expand All @@ -35,7 +35,33 @@ public void Register(string recurringJobId, MethodInfo method, string cron, Time

for (int i = 0; i < parameters.Length; i++)
{
args[i] = Expression.Default(parameters[i].ParameterType);
if (arguments?.Count >= i)
{
if (parameters[i].ParameterType != typeof(string) && arguments[i]?.GetType() == typeof(string))
{
if (string.IsNullOrWhiteSpace((string)arguments[i]))
{
if (parameters[i].ParameterType.IsValueType)
{
arguments[i] = Activator.CreateInstance(parameters[i].ParameterType);
}
arguments[i] = null;
}
}

if (Nullable.GetUnderlyingType(parameters[i].ParameterType) != null && arguments[i] == null)
{
args[i] = Expression.Constant(null, parameters[i].ParameterType);
}
else
{
args[i] = Expression.Constant(Convert.ChangeType(arguments[i], parameters[i].ParameterType), parameters[i].ParameterType);
}
}
else
{
args[i] = Expression.Default(parameters[i].ParameterType);
}
}

var x = Expression.Parameter(method.DeclaringType, "x");
Expand Down
18 changes: 10 additions & 8 deletions src/Hangfire.RecurringJobAdmin/Core/StorageAssemblySingleton.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Hangfire.Annotations;
using System;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
Expand All @@ -14,10 +13,10 @@ private StorageAssemblySingleton()
}

private static StorageAssemblySingleton _instance;
private string[] prefixIgnore = new[] { "Hangfire.RecurringJobAdmin.dll", "Microsoft." };
private string[] prefixIgnore = { "Hangfire.RecurringJobAdmin.dll", "Microsoft." };


public List<Assembly> currentAssembly { get; private set; } = new List<Assembly>();
public List<Assembly> currentAssembly { get; } = new List<Assembly>();

internal static StorageAssemblySingleton GetInstance()
{
Expand Down Expand Up @@ -46,9 +45,12 @@ internal void SetCurrentAssembly(bool includeReferences = false, params Assembly

public bool IsValidType(string type) => currentAssembly.Any(x => x.GetType(type) != null);

public bool IsValidMethod(string type, string method) => currentAssembly?
.FirstOrDefault(x => x.GetType(type) != null)?.GetType(type)?.GetMethod(method) != null;


public bool IsValidMethod(string type, string method, int args)
{
return currentAssembly?.FirstOrDefault(x => x.GetType(type) != null)
?.GetType(type)
?.GetMethods()
.Any(m => m.Name == method && m.GetParameters().Length == args) != null;
}
}
}
60 changes: 32 additions & 28 deletions src/Hangfire.RecurringJobAdmin/Dashboard/JobExtension.html
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,18 @@
<input type="text" class="form-control" v-model="job.Queue" name="queue" id="queue" placeholder="Enter Queue Name">
</div>

<div class="form-group" v-show="job.Arguments && job.Arguments.length">
<label>Arguments</label>
<input v-for="(arg, index) in job.Arguments" type="text" class="form-control" v-model="arg.value" name="argument" id="argument" placeholder="Enter argument value">
</div>
<div class="form-group">
<p v-if="errors.length> 0">
<button type="button" class="btn btn-success" @click="addArgument">
Add argument
</button>
</div>

<div class="form-group">
<p v-if="errors && errors.length">
<b style="color:red">Please correct the following error(s):</b>
<ul>
<li v-for="error in errors" style="color:red">{{ error }}</li>
Expand Down Expand Up @@ -212,11 +222,12 @@ <h1 class="page-header">Recurring Jobs <span class="badge badge-warning">{{getIt
job: {
Id: '',
Cron: '',
Queue: '',
Queue: 'default',
TimeZoneId: '',
Class: '',
Method: '',
JobState: ''
JobState: '',
Arguments: [ { value:'' }]
},
pagination: {
parPage: 10,
Expand All @@ -235,7 +246,6 @@ <h1 class="page-header">Recurring Jobs <span class="badge badge-warning">{{getIt
GetJob(_Id) {
this.title = 'Edit Job';
axios.get('JobConfiguration/GetJob?Id=' + _Id).then(response => {

if (response.data != null) {
this.showModal = true;
this.job.Id = response.data.Object.Id;
Expand All @@ -244,7 +254,12 @@ <h1 class="page-header">Recurring Jobs <span class="badge badge-warning">{{getIt
this.job.Class = response.data.Object.Class;
this.job.Method = response.data.Object.Method;
this.job.TimeZoneId = response.data.Object.TimeZoneId;

this.job.Arguments = [];
if (response.data.hasOwnProperty("Arguments") && Array.isArray(response.data.constructor)) {
response.data.object.Arguments.forEach(function (arg) {
this.job.Arguments.push({ value: arg });
});
}
}
}).catch(e => {
console.log(e);
Expand Down Expand Up @@ -301,17 +316,7 @@ <h1 class="page-header">Recurring Jobs <span class="badge badge-warning">{{getIt
},
UpdateJob(job) {
if (this.checkForm()) {
var arr = [];

for (var key in job) {
if (job.hasOwnProperty(key)) {
arr.push(key + '=' + job[key]);
}
};

var params = arr.join('&');

axios.get('JobConfiguration/UpdateJobs?' + params).then(response => {
axios.get('JobConfiguration/UpdateJobs', { params: job }).then(response => {

if (!response.data.Status) {

Expand Down Expand Up @@ -347,9 +352,10 @@ <h1 class="page-header">Recurring Jobs <span class="badge badge-warning">{{getIt
this.job = {
Id: '',
Cron: '',
Queue: '',
Queue: 'default',
Class: '',
Method: '',
Arguments: [{ value: '' }]
};
this.errors = [];
this.showModal = false;
Expand All @@ -366,21 +372,19 @@ <h1 class="page-header">Recurring Jobs <span class="badge badge-warning">{{getIt
if (!this.job.Cron) {
this.errors.push("Cron is required.");
}
if (!this.job.TimeZoneId) {
this.errors.push("Time Zone is required.");
}
if (!this.job.Class) {
this.errors.push("Class is required.");
}
if (!this.job.Method) {
this.errors.push("Methodo is required.");
}
if (!this.job.Queue) {
this.errors.push("Queue is required.");
this.errors.push("Method is required.");
}

if (!this.errors.length) return true;

if (this.errors.length) return false;

//e.preventDefault();
return !this.errors.length;
},
addArgument() {
this.job.Arguments.push({ value: '' });
},
capitalizeString(s) {
return s.charAt(0).toUpperCase() + s.slice(1);
Expand All @@ -404,7 +408,7 @@ <h1 class="page-header">Recurring Jobs <span class="badge badge-warning">{{getIt
else return null;
},
getPageCount: function () {
return Math.ceil(this.jobs.length / this.pagination.parPage);
return Math.ceil((this.jobs && this.jobs.length) / this.pagination.parPage);
}
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
</PropertyGroup>

<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
<TargetFrameworks>netstandard2.0;net462</TargetFrameworks>
<TargetFrameworks>net462</TargetFrameworks>
</PropertyGroup>

<PropertyGroup Condition=" '$(OS)' == 'Windows_NT' ">
Expand Down Expand Up @@ -86,8 +86,8 @@

<ItemGroup>
<PackageReference Include="Cronos" Version="0.7.0" />
<PackageReference Include="HangFire.Core" Version="1.7.6" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.1" />
<PackageReference Include="HangFire.Core" Version="1.7.31" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

</Project>
9 changes: 9 additions & 0 deletions src/Hangfire.RecurringJobAdmin/Models/PeriodicJob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Reflection;
using System.Text;
using Hangfire.States;

namespace Hangfire.RecurringJobAdmin.Models
{
Expand All @@ -12,13 +13,21 @@ namespace Hangfire.RecurringJobAdmin.Models
/// </summary>
public class PeriodicJob
{
public PeriodicJob()
{
Queue = EnqueuedState.DefaultQueue;
TimeZoneId = TimeZoneInfo.Local.Id;
}

public string Id { get; set; }
public string Cron { get; set; }
public string Queue { get; set; }

public string Class { get; set; }

public string Method { get; set; }

public List<object> Arguments { get; set; }

public string JobState { get; set; }

Expand Down
33 changes: 20 additions & 13 deletions src/Hangfire.RecurringJobAdmin/Pages/ChangeJobDispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,30 +3,29 @@
using Hangfire.RecurringJobAdmin.Core;
using Hangfire.RecurringJobAdmin.Models;
using Hangfire.States;
using Hangfire.Storage;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace Hangfire.RecurringJobAdmin.Pages
{
internal sealed class ChangeJobDispatcher : IDashboardDispatcher
{
private readonly IStorageConnection _connection;
private readonly RecurringJobRegistry _recurringJobRegistry;

public ChangeJobDispatcher()
{

_connection = JobStorage.Current.GetConnection();
_recurringJobRegistry = new RecurringJobRegistry();
}

public class ArgumentsInput
{
public string value { get; set; }
}

public async Task Dispatch([NotNull] DashboardContext context)
{
Expand All @@ -39,6 +38,13 @@ public async Task Dispatch([NotNull] DashboardContext context)
job.Method = context.Request.GetQuery("Method");
job.Queue = context.Request.GetQuery("Queue");
job.TimeZoneId = context.Request.GetQuery("TimeZoneId");
job.Arguments = new List<object>();

var args = JsonConvert.DeserializeObject<ArgumentsInput[]>("[" + context.Request.GetQuery("Arguments[]") + "]");
foreach (ArgumentsInput arg in args)
{
job.Arguments.Add(arg.value);
}

var timeZone = TimeZoneInfo.Utc;

Expand Down Expand Up @@ -68,7 +74,7 @@ public async Task Dispatch([NotNull] DashboardContext context)

return;
}


if (!StorageAssemblySingleton.GetInstance().IsValidType(job.Class))
{
Expand All @@ -80,7 +86,7 @@ public async Task Dispatch([NotNull] DashboardContext context)
return;
}

if (!StorageAssemblySingleton.GetInstance().IsValidMethod(job.Class, job.Method))
if (!StorageAssemblySingleton.GetInstance().IsValidMethod(job.Class, job.Method, job.Arguments.Count))
{
response.Status = false;
response.Message = "The Method not found";
Expand All @@ -91,18 +97,19 @@ public async Task Dispatch([NotNull] DashboardContext context)
}


var methodInfo = StorageAssemblySingleton.GetInstance().currentAssembly
.Where(x => x?.GetType(job.Class)?.GetMethod(job.Method) != null)
.FirstOrDefault()
.GetType(job.Class)
.GetMethod(job.Method);
var methodInfo = StorageAssemblySingleton.GetInstance()
.currentAssembly
.FirstOrDefault(x => x?.GetType(job.Class)?.GetMethods().Any(m => m.Name == job.Method) == true)
?.GetType(job.Class)
.GetMethods().FirstOrDefault(m => m.Name == job.Method && m.GetParameters().Length == job.Arguments.Count);

_recurringJobRegistry.Register(
job.Id,
methodInfo,
job.Cron,
timeZone,
job.Queue ?? EnqueuedState.DefaultQueue);
job.Queue ?? EnqueuedState.DefaultQueue,
job.Arguments);


context.Response.StatusCode = (int)HttpStatusCode.OK;
Expand Down
4 changes: 3 additions & 1 deletion src/Hangfire.RecurringJobAdmin/Pages/GetJobDispatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Text;
Expand Down Expand Up @@ -55,7 +56,8 @@ public async Task Dispatch([NotNull] Dashboard.DashboardContext context)
LastJobState = x.LastJobState,
NextExecution = x.NextExecution.HasValue ? x.NextExecution.Value.ChangeTimeZone(x.TimeZoneId).ToString("G") : "N/A",
Removed = x.Removed,
TimeZoneId = x.TimeZoneId
TimeZoneId = x.TimeZoneId,
Arguments = x.Job.Args.ToList()
});
});
}
Expand Down
Loading