WebJob Failing on Azure but Locally Running Fine

我与影子孤独终老i 提交于 2019-12-25 08:31:45

问题


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

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;
       }
    }
}

回答1:


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:




回答2:


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)



来源:https://stackoverflow.com/questions/41995465/webjob-failing-on-azure-but-locally-running-fine

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!