OrderService is always NULL in production but not in Dev. environment

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
Il y a 3 ans
Dear NopCommerce Community,

I have an odd situation. I just created a payment plugin (Mollie) which is working fine, although in local environment.

I have a callback method in the same controller as the configure methods. The callback is being called by the payment provider after payment. This is happens successfully. After this I call the _OrderService to retrieve the order by ordernumber, also this happens successfully in localhost BUT not in PRODUCTION. There I get NullReferenceException.

Here is my code: (the important part)

[HttpPost]
        public async Task<IActionResult> MollieWebHook(string id)
        {
            _logger.Information("ID = " + id);

            OrderResponse retrieveOrder = await _mollieOrderClient.GetOrderAsync(id);
            _logger.Information(retrieveOrder.OrderNumber);

            IOrderService orderService = EngineContext.Current.Resolve<IOrderService>();
            var order = orderService.GetOrderById(Convert.ToInt32(retrieveOrder.OrderNumber));

            order.PaymentStatus = MolliePaymentStatusToNopCommercePaymentStatus(retrieveOrder.Status);

            return Ok(200);
        }


orderService is null. Also when I use DI in the CTOR

Please help, I have no idea what could cause this ONLY in production?
Il y a 3 ans
RE: "orderService is null"
Check the System Log to see if Resolve had any errors
Il y a 3 ans
New York thank you for your answer.

No Resolve does not trow an error. Not in system log.

I do have an Loglevel: Error of type: Object reference not set to an instance of an object.

System.NullReferenceException: Object reference not set to an instance of an object.
   at Nop.Plugin.Payments.MolliePayments.Controllers.PaymentMolliePaymentsController.MollieWebHook(String id)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeActionMethodAsync>g__Awaited|12_0(ControllerActionInvoker invoker, ValueTask`1 actionResultValueTask)
   at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeNextActionFilterAsync>g__Awaited|10_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted)

And so on
Il y a 3 ans
In my Mollie Payment Plugin I set the webhookURL as

string webhookUrl = _webHelper.GetStoreLocation() + "mollie/webhook/" + order.Id.ToString();

then have have a route to

[IgnoreAntiforgeryToken]
public virtual IActionResult MollieWebhook(int? orderId, string id)
{
......
            if (orderId.HasValue)
            {
                //Load order by identifier (if provided)
                order = _orderService.GetOrderById(orderId.Value);
            }
......
}
Il y a 3 ans
It's being disposed before the GetOrderAsync await returns, which probably happens quickly enough locally but takes too long in production.  

It's not ideal, but you can force GetOrderAsync to run synchronously with a .Wait():
https://www.nopcommerce.com/en/boards/topic/82302/call-async-method-from-nopcommerce-service-layer

Or another approach to try: https://www.nopcommerce.com/en/boards/topic/55357/long-running-scheduled-tasks#211833
Il y a 3 ans
af1racing you are totally right, and I appriciate your answer verry much. But how do I Wait for this specific task since it is not a void.

Task.AwaitAll(); is not the answer.

Do you meby have an example or a tip to work with?

Much appriciated!
Il y a 3 ans
I believe it would be something like:


var retrieveOrderTask = Task.Run(() =>(_mollieOrderClient.GetOrderAsync(id));
retrieveOrderTask.Wait();
var retrieveOrder = retrieveOrderTask.Result;


You could also try making the synchronous part of your method into a task, chain them together with ContinueWith(), and then await both tasks:
https://stackoverflow.com/questions/55647455/why-is-dispose-called-before-its-finishes-async-task
Il y a 3 ans
Once again thank you for the quick answer.

I got the following code (sharing just to show):


[HttpPost]
        public IActionResult MollieWebHook(string id)
        {
            var retrieveOrderTask = Task.Run(() => (_mollieOrderClient.GetOrderAsync(id)));
            retrieveOrderTask.Wait();
            var result = retrieveOrderTask.Result;

            Order order = _orderService.GetOrderById(Convert.ToInt32(result.OrderNumber));
            order.PaymentStatus = MolliePaymentStatusToNopCommercePaymentStatus(result.Status);

            return Ok(200);
        }


But I still get the 'Object reference not set to an instance of an object.' exception.
Il y a 3 ans
try resolving orderservice after the wait:


[HttpPost]
        public IActionResult MollieWebHook(string id)
        {
            var retrieveOrderTask = Task.Run(() => (_mollieOrderClient.GetOrderAsync(id)));
            retrieveOrderTask.Wait();
            var result = retrieveOrderTask.Result;

            var orderService= EngineContext.Current.Resolve<IOrderService>();
            Order order = orderService.GetOrderById(Convert.ToInt32(result.OrderNumber));
            order.PaymentStatus = MolliePaymentStatusToNopCommercePaymentStatus(result.Status);

            return Ok(200);
        }


if that doesn't work, set some break points so we know exactly what is null
Il y a 3 ans
Sadly but it dit not work. Also I did a little loging. And the problem is with IOrderService being NULL

First log is information log: ord_023ki...
Second log is the result.OrderNumber: 3255
Then I did a loggin on orderService and got: OrderService Nop.Services.Orders.OrderService

Then I added a Warning log in case orderService == null > The warning is Order object is null

So orderObject is definetly null

Because after that I got a NullReference Error
This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.