The type does not contain a method with signature `SendFromQueue(Int32)`


#1

I have set up Hangfire with Autofac within ASP.NET Web API application.

The exception "The type does not contain a method with signature SendFromQueue(Int32)" happens when Hangfire tries to enqueue a job. The job is successfully scheduled and uses ID to a content stored in database (so I only pass the ID parameter to the service method call).

This is what my scheduled job looks like in Hangfire dashboard:

using MyServices;

MailerService mailerService = Activate<MailerService>();
mailerService.SendFromQueue(2);

The exception:

Failed Can not change the state of a job to ‘Enqueued’: target method was not found.
System.InvalidOperationException

The type MyServices.MailerService does not contain a method with signature SendFromQueue(Int32)

System.InvalidOperationException: The type MyServices.MailerService does not contain a method with signature SendFromQueue(Int32)
at HangFire.Storage.InvocationData.Deserialize()

How I schedule:

// add to HangFire schedule
BackgroundJob.Schedule<MailerService>(ms => ms.SendFromQueue(queued.Id), TimeSpan.FromMinutes(2));

And my Autofac registration within Startup.cs:

		// hangfire config
		app.UseHangfire(config =>
		{
			config.UseAutofacActivator(container);
			config.UseSqlServerStorage("DefaultConnection");
			config.UseServer();
		});

What is going on? I don’t want to use static service methods, that’s why it has to work with instance method with instance being provided by Autofac.


#2

@mare, big sorry for the delay – whole 16 days :frowning: Do you still have this problem?


#3

Unfortunately yes. I was working on some other stuff in the meantime and had some time off. This issue remains. Don’t know how to solve this.


#4

Can you post here the signature of the MailerService.ms.SendFromQueue method?


#5

sure thing

Here’s the code for the service method:

	public void SendFromQueue(int mailMessageId)
	{
		if (!HasBeenSent(mailMessageId))
		{
			var queued = Load(mailMessageId);
			if (!string.IsNullOrWhiteSpace(queued.MessageSerialized))
			{
				try
				{
					var messageDto = JsonConvert.DeserializeObject<MailMessageDto>(queued.MessageSerialized);
					if (messageDto != null)
					{
						SendSimpleEmail(messageDto);
						SetSent(mailMessageId);
					}
				}
				catch (Exception e)
				{
					// handle exception
				}
			}
		}
	}

The service has a bunch of non-parameterless constructors but all of them use dependencies that are registered with Autofac.

The service itself is registered with Autofac like this:

		// mailing
		builder.RegisterType<MailerService>().AsSelf();

I basically followed your best practices which make lots of sense here http://docs.hangfire.io/en/latest/users-guide/best-practices.html

I’m scheduling this within a custom action filter attribute (AOPish kind of way):

public override async Task OnActionExecutedAsync(HttpActionExecutedContext actionExecutedContext, CancellationToken cancellationToken)
  {
    if (actionExecutedContext.Response != null && actionExecutedContext.Response.IsSuccessStatusCode)
    {
      ...        
      // add to HangFire schedule
      BackgroundJob.Schedule<MailerService>(ms => ms.SendFromQueue(queued.Id), TimeSpan.FromMinutes(2));
      ...
    }
  }

Thank you


#6

Where the SendFromQueue method is defined? In the MailerService class itself, or in its base class?


#7

MailerService does inherit a base ServiceBase class but the SendFromQueue is defined inside the MailerService class and nowhere else.


#8

O_o this is very interesting… This exception occurs because the type.GetMethod(Method, parameterTypes); returns null value. We can achieve this result when:

  • The type variable points to different type. Do you have another MailerService type loaded in your application domain?
  • Method and parameterTypes values are wrong, however we can see that they are correct.
  • Target method visibility is not public, but we can see it is public from the code snippet above.
  • Target method is declared in one of base classes, but you denied it (by the way, this is a wrong behavior).

Do you know other ways to receive the null result after calling the GetMethod method?


#9

this is plain old Reflection that HangFire uses? don’t know what could be wrong here…Is there a way for me to debug into HangFire on this?


#10

Sergey,

this still remains an unresolved issue. Is it possible that somehow the activator does not create a service instance when trying to run the scheduled job? And subsequently doesn’t find the requested method?

My add to queue code works (the MailerService is registered within AutoFac and AutoFac does resolve it at runtime when inside my code):

// add to mail queue (this works)
var queued = await MailerService.AddToQueue(mailMsgDto);

// add to HangFire schedule
BackgroundJob.Schedule<MailerService>(ms => ms.SendFromQueue(queued.Id), TimeSpan.FromMinutes(2));

How does Aufofac activator actually create service instances for background jobs?


#11

btw I added a default constructor to MailerService where I just new() up some dependencies but same exception still occurs


#12

I added Hangfire.Core project to my solution to be able to debug it and the InvocationData.Deserialize() always managed to find the method when in Debug session. Job still failed couple of times then after few more retries it just succeeded one time. However, emails still weren’t sent.


#13

whoa, after debugging this I finally got it resolved. The problem actually was in the SendFromQueue() method which was failing to deserialize our MailMessageDto which we serialized in the AddToQueue() step. The issue was with the System.Net.MailAddress class. This didn’t show up until I debugged deep down into my code.

thank you


#14

Seems that anytime something goes wrong within our jobs the above exception occurs. I just ran into some issues with async which resulted in Thread being aborted exception within my jobs (yes, I know async is not yet supported, just read about that) and that same exception was being thrown within Hangfire.

Is there a way that exception details would somehow be propagated into the Dashboard?


#15

I’m experiencing this same issue. The really weird thing is if I requeue the Background Job a couple of times it will eventually succeed.


#16

Please check if you have multiple Hangfire servers registered (running) with different codebases. In my case, it was our production server and my own development server. I was testing on my own development machine with newer code but the scheduled Jobs somehow ended to be run by the production server (which had old code, lacking some crucial methods etc.) thus resulting in this exception.


Job throws - System.TypeLoadException
#17

#18

Spot on! We are two developers on code bases that don’t currently match. Thank you!


#19

We’ve found that LocalDB seems to work perfectly well, e.g. with:

<add name="connstringname" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDB)\v11.0;AttachDbFilename=|DataDirectory|\local.mdf;Integrated Security=True" />

No stepping on each others toes :slight_smile:


#20

Sure, it does, it’s SQL Server but then you have to keep those LocalDBs in sync with each other…