Hangfire: Unable to resolve service for type 'System.String'

Created on 22 Jun 2017  ·  9Comments  ·  Source: HangfireIO/Hangfire

Hi All,

I'm having an issue running all of my Jobs using Hangfire v1.6.14 with ASP.NET Core v1.1.2. I have no doubt it's probably something I'm doing wrong so apologies in advance. I'm calling the BackgroundJob from a controller.

The error I'm receiving:

An exception occurred during processing of a background job.
System.InvalidOperationException
Unable to resolve service for type 'System.String' while attempting to activate 'SHLNG_AMS.LDAP_Auth.LDAPSync'.
System.InvalidOperationException: Unable to resolve service for type 'System.String' while attempting to activate 'SHLNG_AMS.LDAP_Auth.LDAPSync'.
   at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
   at Hangfire.AspNetCore.AspNetCoreJobActivatorScope.Resolve(Type type)
   at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
   at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_0.<PerformJobWithFilters>b__0()
   at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func`1 continuation)
   at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable`1 filters)
   at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
   at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)

Any ideas?

Most helpful comment

What are the constructors for SHLNG_AMS.LDAP_Auth.LDAPSync ?

It likely has an argument that is of type string, and the activator is trying to instantiate, but Asp.Net Core's default dependency injection has nothing defined for type string ( of course ).

I haven't done .Core work, so I can't tell you exactly what you need, but you probably need to define the string argument that LDAPSync is using so that it can create that instance.

In Unity, this is done by:

IUnityContainer container = new UnityContainer() .RegisterType<MyObject>( new InjectionConstructor(someInt, someString, someDouble));

where the constructor takes three arguments, and int, string, and double.

Here's info on it from Asp.net Core:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection

All 9 comments

What are the constructors for SHLNG_AMS.LDAP_Auth.LDAPSync ?

It likely has an argument that is of type string, and the activator is trying to instantiate, but Asp.Net Core's default dependency injection has nothing defined for type string ( of course ).

I haven't done .Core work, so I can't tell you exactly what you need, but you probably need to define the string argument that LDAPSync is using so that it can create that instance.

In Unity, this is done by:

IUnityContainer container = new UnityContainer() .RegisterType<MyObject>( new InjectionConstructor(someInt, someString, someDouble));

where the constructor takes three arguments, and int, string, and double.

Here's info on it from Asp.net Core:

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection

Having the same issue too trying to use Hangfire to send emails in the background to improve response time and perceived performance. Below is the exception message (in details) I get:

System.InvalidOperationException

Unable to resolve service for type 'System.String' while attempting to activate 'GlobalLoyaltyEngine.DomainServices.Generic.Utility.MailSender'.

System.InvalidOperationException: Unable to resolve service for type 'System.String' while attempting to activate 'GlobalLoyaltyEngine.DomainServices.Generic.Utility.MailSender'.
at Microsoft.Extensions.Internal.ActivatorUtilities.ConstructorMatcher.CreateInstance(IServiceProvider provider)
at Hangfire.AspNetCore.AspNetCoreJobActivatorScope.Resolve(Type type)
at Hangfire.Server.CoreBackgroundJobPerformer.Perform(PerformContext context)
at Hangfire.Server.BackgroundJobPerformer.<>c__DisplayClass8_0.b__0()
at Hangfire.Server.BackgroundJobPerformer.InvokePerformFilter(IServerFilter filter, PerformingContext preContext, Func1 continuation) at Hangfire.Server.BackgroundJobPerformer.PerformJobWithFilters(PerformContext context, IEnumerable1 filters)
at Hangfire.Server.BackgroundJobPerformer.Perform(PerformContext context)
at Hangfire.Server.Worker.PerformJob(BackgroundProcessContext context, IStorageConnection connection, String jobId)

I queue the operation like so:
BackgroundJob.Enqueue(() => mailSender.PushMail(mailRecipient, message, mailSenderAddress, subject, true));

Excerpts from the mail sender class:

` public class MailSender
{
public MailSender(string username, string password, int port, string smtpServer)
{
_mailMessage = new MimeMessage();

        this.port = port;
        this.smtpServer = smtpServer;
        this.username = username;
        this.password = password;
        this.ccRecipients = new List<string>();
    }

    private int port;
    private string smtpServer;
    private string username;
    private string password;
    private List<string> ccRecipients;
    private MimeMessage _mailMessage;

    public bool PushMail(string addressee, string message, string addresser, string subject, bool isHtmlContent)
    {
        var addresserEmail = !string.IsNullOrEmpty(addresser) ? addresser : "[email protected]";
        bool mailSuccessfullySent = false;

        if (!string.IsNullOrEmpty(message))
        {
            if (string.IsNullOrEmpty(addressee))
                throw new ArgumentException("Recipient email address cannot be empty or null.");

            _mailMessage.From.Add(new MailboxAddress("Global Loyalty Service", addresserEmail));

            AddMessageRecipients(addressee, _mailMessage);

            _mailMessage.Subject = subject;
            _mailMessage.Priority = MessagePriority.Urgent;
            _mailMessage.Body = new TextPart(isHtmlContent ? TextFormat.Html : TextFormat.Plain)
            {
                Text = message
            };

            IncludeCarbonCopyRecipients(_mailMessage);

            try
            {
                using (var smtpClient = new SmtpClient())
                {
                    smtpClient.Connect(smtpServer, port, MailKit.Security.SecureSocketOptions.Auto);
                    smtpClient.Authenticate(new NetworkCredential(username, password));

                    smtpClient.Send(_mailMessage);
                    smtpClient.Disconnect(true);

                    mailSuccessfullySent = true;
                }

            }
            catch (Exception ex)
            {
                var exceptionMessage = ex.Message;
            }
        }

        return mailSuccessfullySent;
    }
    .....

}`

@ace26 The constructor of your MailSender class requires three strings and a int to be instantiated. Where do you expect those to come from when Hangfire needs to instantiate the MailSender class?

@burningice2866 I left out the part where the MailSender class is instantiated with those values in the excerpt I shared but the appropriate values are passed to the constructor for instantiation.
While debugging I checked to be sure everything needed was passed in so there is no problem in the regard you highlighted.

Clicking on the job on Hangfire dashboard shows this:

// Job ID: #7 using GlobalLoyaltyEngine.DomainServices.Generic.Utility; var mailSender = Activate<MailSender>(); await mailSender.PushMailAsync("[email protected]","hello","[email protected]","Password Reset Request", false);

And then the exception message.

Your error message suggests that Hangfire is trying to call the constructor
through dependency injection and doesn't have any information about the
string arguments.

Whatever class is invoked when enqueuing must be instantiable by dependency
injection... Through the job activator.

  • Daniel

On Sun, Aug 13, 2017, 7:43 PM Oswald Umeh notifications@github.com wrote:

@burningice2866 https://github.com/burningice2866 I left out the part
where the MailSender class is instantiated with those values in snippet I
shared but the appropriate values are passed to the constructor for
instantiation.


You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub
https://github.com/HangfireIO/Hangfire/issues/924#issuecomment-322074992,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AAO4fSteRaMFhX7sXycujKNgJMF13-D1ks5sX4oMgaJpZM4OCrwH
.

@ace26 you're missing the point... it doesn't matter how you are instantiating it. What matters is how Hangfire can instantiate it and my question was rhetorical trying to get you to realize on your own why your setup cannot work.

As @danielcor points out - when enqueuing calls to instance-methods its crucial that the class either has a parameterless constructor or that all parameters can be resolved via DI. While you might think that Hangfire will call the method on the emailSender-instance you've created for calling the Enqueue method, that is not the case.

@burningice2866 Figured that out reading @danielcor comment and taking a second look at the exception message again.
Thanks.

Yep....it was user error. @dcorbett-fivebridgesllc put me on right path so thank you. After wrapping the calling instance method in a class which takes the DI parameters in a constructor, everything is now working 👍

Thanks for your help everyone!

@K1tson , Even I am getting the same error.
Can you please post the code that worked for you?
Thanks in advance.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

osmanrahimi picture osmanrahimi  ·  3Comments

nsnail picture nsnail  ·  3Comments

plmwong picture plmwong  ·  3Comments

cindro picture cindro  ·  3Comments

JvanderStad picture JvanderStad  ·  3Comments