0

I'm running a WebJob locally -- still connecting to the same Storage service on Azure -- but when I publish it on Azure, it's failing.

It was failing locally as well with the same error but I was able to fix it and run it perfectly fine on my local dev machine. Any idea why it may fail on Azure?.

To reiterate the point, even though it's running locally, it still connects to the same queue and storage account on Azure. So the only thing that's running locally is the code.

Here's the error I'm getting on Azure Portal under WebJob logs:

Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: Functions.ProcessQueueMessage ---> System.MissingMethodException: No parameterless constructor defined for this object. at System.RuntimeTypeHandle.CreateInstance(RuntimeType type, Boolean publicOnly, Boolean noCheck, Boolean& canBeCached, RuntimeMethodHandleInternal& ctor, Boolean& bNeedSecurityCheck) at System.RuntimeType.CreateInstanceSlow(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.RuntimeType.CreateInstanceDefaultCtor(Boolean publicOnly, Boolean skipCheckThis, Boolean fillCache, StackCrawlMark& stackMark) at System.Activator.CreateInstanceT at Microsoft.Azure.WebJobs.Host.Executors.DefaultJobActivator.CreateInstanceT at Microsoft.Azure.WebJobs.Host.Executors.ActivatorInstanceFactory1.Create() at Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker1.d__0.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.d__31.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.d__2c.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter.ValidateEnd(Task task) at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.d__13.MoveNext() --- End of inner exception stack trace --- at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.d__13.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.d__1.MoveNext()

P.S. I created the WebJob in VS 2015 Cloud -> Azure WebJob. Also, it targets .NET Framework 4.6.2 enter image description here

One other important point, I have an appsettings.json file that contains some setting info. This is in the bin directory. I do read this file and get some settings that are used in my code. When I FTP'ed into the WebJobs directory, I see the appsettings.json file there. Not sure if the issue could be related to that.

UPDATE: Here's Main:

class Program
{
   static readonly IKernel Kernel = new StandardKernel();
   static JobHostConfiguration config;

   static void Main()
   {
      BootStrapIoc();

      var host = new JobHost(config);
      host.RunAndBlock();
   }

   private static void BootStrapIoc()
   {
      Kernel.Load(Assembly.GetExecutingAssembly());
      config = new JobHostConfiguration
      {
         JobActivator = new MyJobActivator(Kernel)
      };
   }
}

Here's MyJobActivator:

public class MyJobActivator : IJobActivator
{
   private readonly IKernel _container;

   public MyJobActivator(IKernel container)
   {
      _container = container;
   }

   public T CreateInstance<T>()
   {
      return _container.Get<T>();
   }
}

Here's my Ninject Bindings class

public class NinjectBindings : Ninject.Modules.NinjectModule
{
   IConfiguration Configuration;

   public override void Load()
   {

      Bind<IConfiguration>().ToMethod(ctx => {
            var builder = new ConfigurationBuilder();
            builder.SetBasePath(Directory.GetCurrentDirectory());
            builder.AddJsonFile("appsettings.json");
            Configuration = builder.Build();
                return Configuration;
            });

       // Bind clients
       var docDbClient = new Clients.DocumentDb.DocumentDbClient(Configuration);

       // Bind Services
       Bind<ISomeService>().To<SomeService>();

       // Bind Repositories
       Bind<ISomeRepository>().To<SomeRepository>();
    }
}

The Functions class looks like this:

public class Functions
{
   private ISomeService _someService;

   public Functions(ISomeService someService)
   {
      _someService = someService;
   }

   public async Task ProcessQueueMessage([QueueTrigger("my-queue")] MyMessageObject message, TextWriter log)
   {
      switch(message.typeId)
      {
         case MyEnum.TypeA:
            _someService.FunctionA(message);
            break;
         case MyEnum.TypeB:
            _someService.FunctionB(message);
            break;
       }
    }
}
Sam
  • 26,817
  • 58
  • 206
  • 383

2 Answers2

0

The exception you get is for

No parameterless constructor defined for this object

The object implementing your queue handling method must have parameterless constructor in order for the JobHost to be able to create it (sorry, that's the best pointer I can give without seeing a code sample)

EranG
  • 822
  • 4
  • 10
  • Just added an update to original post that shows what my Functions class looks like. Just want to understand it clearly. I think you're saying the Functions class must have parameterless constructor, is that correct? Secondly, why is it that it works fine locally then? If the service that I'm passing to the constructor is causing the issue, shouldn't it fail locally too? – Sam Feb 02 '17 at 08:21
0

Microsoft.Azure.WebJobs.Host.FunctionInvocationException: Exception while executing function: Functions.ProcessQueueMessage ---> System.MissingMethodException: No parameterless constructor defined for this object.

According to your description, I tested this issue on my side and I could encountered the same error based on your code. After some trials, I could make it work as expected on my side and Azure. Here are some possible causes, you could refer to them:

Program.cs > Main

IKernel Kernel = new StandardKernel();
Kernel.Load(Assembly.GetExecutingAssembly());
var config = new JobHostConfiguration
{
    JobActivator = new MyJobActivator(Kernel)
};

//Initializes a new instance of the Microsoft.Azure.WebJobs.JobHost class using the configuration provided.
var host = new JobHost(config);
host.RunAndBlock();

For loading appsettings.json file, you could configure your mapper as follows:

Bind<IConfiguration>().ToMethod(ctx =>
{
    var builder = new ConfigurationBuilder();

    //set base path to the current working directory of your application
    builder.SetBasePath(Directory.GetCurrentDirectory());
    builder.AddJsonFile("appsettings.json");
    IConfigurationRoot Configuration = builder.Build();
    return Configuration;
});

Note: Make sure appsettings.json is under the root dir of your project and set "Copy to Output Directory" as Copy always.

My test result:

Bruce Chen
  • 18,207
  • 2
  • 21
  • 35
  • I really appreciate your response. I just updated the original post to show you pretty much all the code I have in this WebJob. I had most of what you're suggesting already but added the missing pieces. Again, the app is working locally fine but on Azure it blows up with the same error message. – Sam Feb 02 '17 at 19:02
  • Could this be an issue with the .NET framework because I'm targeting 4.6.2? I haven't been able to find an answer on whether WebJobs support .NET 4.6.2 or not. – Sam Feb 02 '17 at 20:06
  • My WebJobs project (`not NetCore`) is also target on .NET 4.6.2. Web App has supported this version, you could log in with [KUDU](https://blogs.msdn.microsoft.com/benjaminperkins/2014/03/24/using-kudu-with-windows-azure-web-sites/), click "Debug console > CMD", run this command `cd D:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework` to check the supported version. – Bruce Chen Feb 02 '17 at 21:59
  • Have you checked that your WebJobs could start up successfully? And this error is thrown only when a new message is enqueued? Upon the changes, if you still get the same error `Exception while executing function: Functions.ProcessQueueMessage ---> System.MissingMethodException: No parameterless constructor defined for this object.`, I assumed that you need to follow this [tutorial](https://blogs.msdn.microsoft.com/webdev/2014/11/12/new-developer-and-debugging-features-for-azure-webjobs-in-visual-studio/) to `remote debug` your WebJobs. – Bruce Chen Feb 02 '17 at 22:09
  • I just got it to work. I had to delete the WebJob and publish it fresh. Because I updated it so many times, somehow there must have been some residue from older versions of the code. Fresh publish and the changes suggested here fixed the issue! This was really getting frustrating. Thank you very much for your help! – Sam Feb 02 '17 at 22:13