Umbraco.Commerce.Issues icon indicating copy to clipboard operation
Umbraco.Commerce.Issues copied to clipboard

Dynamic Priced Shipping Method causing a NRE when updating order

Open Rian-BG opened this issue 2 months ago • 3 comments

Which component is this issue related to?

Umbraco Commerce (Core)

Which Umbraco Commerce version are you using? (Please write the exact version, example: 10.1.0)

13.2.2

Bug summary

When selecting a Dynamic Shipping Method configured purely via the back office (no custom calculator code), checkout fails with a NullReferenceException. Flat-rate shipping methods work without issue — only dynamic shipping methods trigger the error.

Code being called:

_commerceApi.Uow.Execute(uow =>
            {
                var store = _settingsService.GetStore();
                var order = _commerceApi.GetOrCreateCurrentOrder(store.Id)
                    .AsWritable(uow)
                    .SetShippingMethod(shippingMethodId);

                _commerceApi.SaveOrder(order);

                uow.Complete();
            });

Specifics

  • No custom shipping calculator implemented
  • Dynamic rate created according to official documentation
  • Order currency & shipping address present and valid
  • ShippingMethodId is correctly assigned to the order on update
  • Only difference between working and failing shipping methods: Dynamic vs Flat

Steps to reproduce

  1. Create a Dynamic Shipping Method via back office:

Add valid pricing rules/bands Save & publish

  1. Add product to cart and proceed to checkout
  2. Select the Dynamic Priced Shipping method and submit form/trigger update of order shipping method/continue with checkout flow
  3. NRE thrown during _api.SaveOrder(order)

Expected result / actual result

Expected Result Order is updated with the correct shipping method and pricing, and no errors are thrown/checkout flow continues as expected

Actual Result A NullReferenceException is thrown when updating the shipping method

Dependencies

No response

Rian-BG avatar Nov 11 '25 12:11 Rian-BG

Hi @Rian-BG ,

I've tried replicating this on our demo store, but the checkout process went through successfully. Could you share some details on your dynamic shipping method configuration, the defined ranges?

Thanks, Adrian

acoumb avatar Nov 11 '25 15:11 acoumb

Hey @acoumb

Thanks for getting back to me so soon.

Please see below the rates set:

Image

I also did test it with only a 1 - Unbound range, assuming that would act as a catch-all.

Rian-BG avatar Nov 11 '25 15:11 Rian-BG

@Rian-BG could you provide the entire configuration (SKU, Countries) of the shipping method config, maybe also the controller action you use?

acoumb avatar Nov 12 '25 08:11 acoumb

Apologies for the wait, busy busy.

Controller action:

public IActionResult UpdateOrderShippingMethod(UpdateOrderShippingMethodDto model)
{
    try
    {
        _checkoutService.UpdateOrderShippingMethod(model.ShippingMethod);
    }
    catch (CommerceException)
    {
        ModelState.AddModelError("", "Failed to set order shipping method");

        return CurrentUmbracoPage();
    }

    if (model.NextStep.HasValue)
        return RedirectToUmbracoPage(model.NextStep.Value);

    return RedirectToCurrentUmbracoPage();
}

Service method:

public void UpdateOrderShippingMethod(Guid? shippingMethodId)
{
    if (shippingMethodId is null || shippingMethodId == Guid.Empty)
        throw new ArgumentNullException(nameof(shippingMethodId));

    try
    {
        //_commerceApi.Uow.Execute(uow =>
        //{
        //    var store = _settingsService.GetStore();
        //    var order = _commerceApi.GetOrCreateCurrentOrder(store.Id)
        //        .AsWritable(uow)
        //        .SetShippingMethod(shippingMethodId);

        //    _commerceApi.SaveOrder(order);

        //    uow.Complete();
        //});

        _commerceApi.Uow.Execute(uow =>
        {
            var store = _settingsService.GetStore();
            var order = _commerceApi.GetOrCreateCurrentOrder(store.Id)
                .AsWritable(uow);

            var selectedShippinOptionId =
            shippingMethodId.HasValue &&
            order.ShippingInfo.ShippingMethodId.HasValue &&
            shippingMethodId == order.ShippingInfo.ShippingMethodId
            ? order.ShippingInfo.ShippingOption?.Id
            : null;

            if (!selectedShippinOptionId.IsNullOrWhiteSpace())
            {
                var shippingMethod = _commerceApi.GetShippingMethod((Guid)shippingMethodId);
                var shippingRateAttempt = shippingMethod.TryCalculateRate(selectedShippinOptionId, order);

                order.SetShippingMethod((Guid)shippingMethodId, shippingRateAttempt.Result.Option);
            }
            else
            {
                order.SetShippingMethod((Guid)shippingMethodId);
            }

            _commerceApi.SaveOrder(order);

            uow.Complete();
        });
    }
    catch (ValidationException ex)
    {
        _logger.LogError(ex, $"An error occurred during updating order shipping method.");
        throw new CommerceException("Failed to update order shipping method.");
    }
}

I attempted to use the Demo Store code, as it had more validation - the commented out version is our original code. However, on calling _commerceApi.SaveOrder(order); it still throws a NRE.

Screenshot of the whole shipping method: https://gyazo.com/7a9401446a7b3504c8b0becf982e1c94

Please let me know if you require anything else.

Rian-BG avatar Nov 26 '25 14:11 Rian-BG

Please find below the objects that are passed in .SaveOrder(order) in the different cases.

Dynamic shipping order.json Flat rate order.json

Rian-BG avatar Dec 02 '25 08:12 Rian-BG