Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: BodySerializationMethod.UrlEncoded with Complex view model class #1795

Open
infofromca opened this issue Aug 28, 2024 · 0 comments
Open
Labels

Comments

@infofromca
Copy link
Contributor

Describe the bug 🐞

I have a very complex class called CheckoutViewModel:
using OrchardCore.Commerce.MoneyDataType;
using System.Collections.Generic;

namespace OrchardCore.Commerce.Payment.ViewModels;

public class CheckoutViewModel : PaymentViewModel //, ICheckoutViewModel
{
    public string? ShoppingCartId { get; set; }

    public Amount GrossTotal { get; set; } = new();

    // [BindNever]
  //  public IEnumerable<OrchardCore.Commerce.Abstraction.ViewModels.Region> Regions { get; set; } = Array.Empty<OrchardCore.Commerce.Abstraction.ViewModels.Region>();

   // [BindNever]
    public IDictionary<string, IDictionary<string, string>> Provinces { get; set; } =
        new Dictionary<string, IDictionary<string, string>>();

    public string? UserEmail { get; set; }

    public bool IsInvalid { get; set; }

  //  public IEnumerable<IShape> CheckoutShapes { get; set; } = Array.Empty<IShape>();

    //public CheckoutViewModel(OrderPart orderPart, Amount singleCurrencyTotal, Amount netTotal)
    //    : base(orderPart, singleCurrencyTotal, netTotal) =>
    //    Metadata.Type = "Checkout";

    //public CheckoutViewModel()
    //    : base() =>
    //    Metadata.Type = "Checkout";
}
//using Microsoft.AspNetCore.Mvc.ModelBinding;
using OrchardCore.Commerce.Abstractions.Abstractions;
using OrchardCore.Commerce.Abstractions.Models;
using OrchardCore.Commerce.MoneyDataType;
using OrchardCore.Commerce.Payment.Abstractions;
//using OrchardCore.DisplayManagement.Views;
using System.Collections.Generic;
using System.Threading.Tasks;
using BlazingOrchard.DisplayManagement.Services;
using BlazingOrchard.DisplayManagement.Shapes;
using BlazingOrchard.DisplayManagement.Zones;
using System.Linq;

namespace OrchardCore.Commerce.Payment.ViewModels;

public class PaymentViewModel : IPaymentViewModel //ShapeViewModel ,
{
    public Amount SingleCurrencyTotal { get; set; } = new();

    public Amount NetTotal { get; set; } = new();

    public OrderPart OrderPart { get; set; } = new();

    //[BindNever]
    public IDictionary<string, object> PaymentProviderData { get; set; } = new Dictionary<string, object>();

    public PaymentViewModel(OrderPart orderPart, Amount singleCurrencyTotal, Amount netTotal)
    {
        OrderPart = orderPart;
        SingleCurrencyTotal = singleCurrencyTotal;
        NetTotal = netTotal;
    }
    public PaymentViewModel()
    {
      
    }
    //public async Task WithProviderDataAsync(IEnumerable<IPaymentProvider> paymentProviders)
    //{
    //    foreach (var provider in paymentProviders)
    //    {
    //        if (await provider.CreatePaymentProviderDataAsync(this) is { } data)
    //        {
    //            PaymentProviderData[provider.Name] = data;
    //        }
    //    }
    //}

    //private ShapeMetadata _metadata;
    //public ShapeMetadata Metadata
    //{
    //    get
    //    {
    //        return _metadata ??= new ShapeMetadata();
    //    }
    //    set
    //    {
    //        _metadata = value;
    //    }
    //}

    //public string Position
    //{
    //    get
    //    {
    //        return Metadata.Position;
    //    }

    //    set
    //    {
    //        Metadata.Position = value;
    //    }
    //}

    //public string Id { get; set; }
    //public string TagName { get; set; }

    //private List<string> _classes;
    //public IList<string> Classes
    //{
    //    get { return _classes ??= new List<string>(); }
    //    set { _classes = (List<string>)value; }
    //}

    //private Dictionary<string, string> _attributes;
    //public IDictionary<string, string> Attributes
    //{
    //    get { return _attributes ??= new Dictionary<string, string>(); }
    //    set { _attributes = (Dictionary<string, string>)value; }
    //}

    //private Dictionary<string, object> _properties;
    //public IDictionary<string, object> Properties
    //{
    //    get { return _properties ??= new Dictionary<string, object>(); }
    //    set { _properties = (Dictionary<string, object>)value; }
    //}

    //private bool _sorted = false;

    //private List<IPositioned> _items;
    //public IReadOnlyList<IPositioned> Items
    //{
    //    get
    //    {
    //        _items ??= new List<IPositioned>();

    //        if (!_sorted)
    //        {
    //            _items = _items.OrderBy(x => x, FlatPositionComparer.Instance).ToList();
    //            _sorted = true;
    //        }

    //        return _items;
    //    }
    //}
}

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using OrchardCore.Commerce.Abstractions.Abstractions;
using OrchardCore.Commerce.Abstractions.Fields;
using OrchardCore.ContentFields.Fields;
using OrchardCore.ContentManagement;
using System.Collections.Generic;

namespace OrchardCore.Commerce.Abstractions.Models;

public class OrderPart : ContentPart
{
    public TextField OrderId { get; set; } = new();
    public TextField Status { get; set; } = new();

    /// <summary>
    /// Gets the order's line items.
    /// </summary>
    public IList<OrderLineItem> LineItems { get; set; } = new List<OrderLineItem>();

    /// <summary>
    /// Gets additional costs that don't belong to an <see cref="OrderLineItem"/>, such as taxes and shipping.
    /// </summary>
    public IList<OrderAdditionalCost> AdditionalCosts { get; set; } = new List<OrderAdditionalCost>();

    /// <summary>
    /// Gets the amounts charged for this order. Typically a single credit card charge.
    /// </summary>

    // This is a temporary solution, it needs to be reworked in the future!
#pragma warning disable CA2326 // Do not use TypeNameHandling values other than None
#pragma warning disable SCS0028 // TypeNameHandling is set to the other value than 'None'. It may lead to deserialization vulnerability.
    [JsonProperty(ItemTypeNameHandling = TypeNameHandling.Auto)]
#pragma warning restore SCS0028 // TypeNameHandling is set to the other value than 'None'. It may lead to deserialization vulnerability.
#pragma warning restore CA2326 // Do not use TypeNameHandling values other than None
    public IList<IPayment> Charges { get; set; } = new List<IPayment>();

    public TextField Email { get; set; } = new();
    public TextField Phone { get; set; } = new();
    public TextField VatNumber { get; set; } = new();

    public AddressField BillingAddress { get; set; } = new();
    public AddressField ShippingAddress { get; set; } = new();
    public BooleanField BillingAndShippingAddressesMatch { get; set; } = new();
    public BooleanField IsCorporation { get; set; } = new();

    public IDictionary<string, JToken> AdditionalData { get; set; } = new Dictionary<string, JToken>();
}

Step to reproduce

[Post("/api/checkout/confirm/{providerName}/{paymentIntentId}/{shoppingCartId}?middleUrl={middleUrl}")]
Task ConfirmPaymentAsync(
string providerName,
string paymentIntentId,
string shoppingCartId,
string middleUrl,
[Body(BodySerializationMethod.UrlEncoded)] CheckoutViewModel checkoutViewModel,
CancellationToken cancellationToken = default);
2. Click on submit to have a http post aync calling to api server
3. Scroll down to it hit the api server which is ok .
4. See error
but I got this 👍 POST /api/checkout/confirm/Stripe/pi_3PsrfnRpyWVeDn6H0MxBWbGo_secret_r7Q8wEngIEPH0JeVjLzfuCECs/4hap81e272txkszm6jrryh52xj?middleUrl=guangmauiauth HTTP/1.1
Host: localhost:62354
Content-Type: application/x-www-form-urlencoded
Content-Length: 544

RegionList=System.Collections.Generic.List%601%5BOrchardCore.Commerce.Abstraction.ViewModels.Region%5D&ShoppingCartId=4hap81e272txkszm6jrryh52xj&GrossTotal=%240.00&Provinces=System.Collections.Generic.Dictionary%602%5BSystem.String%2CSystem.Collections.Generic.IDictionary%602%5BSystem.String%2CSystem.String%5D%5D&UserEmail=&IsInvalid=False&SingleCurrencyTotal=%243.00&NetTotal=%243.00&OrderPart=OrchardCore.Commerce.Abstractions.Models.OrderPart&PaymentProviderData=System.Collections.Generic.Dictionary%602%5BSystem.String%2CSystem.Object%5D

UserEmail=&IsInvalid=False&SingleCurrencyTotal=%243.00&NetTotal=%243.00 are ok,
but OrderPart=OrchardCore.Commerce.Abstractions.Models.OrderPart&PaymentProviderData=System.Collections.Generic.Dictionary%602%5BSystem.String%2CSystem.Object%5D just gave out the name of the another class , not the data.

Reproduction repository

https://github.com/reactiveui/refit

Expected behavior

OrderPart=OrchardCore.Commerce.Abstractions.Models.OrderPart&PaymentProviderData=System.Collections.Generic.Dictionary%602%5BSystem.String%2CSystem.Object%5D
should show the data like
CheckoutViewModel.OrderPart.Email=[email protected]&....

Screenshots 🖼️

No response

IDE

No response

Operating system

No response

Version

No response

Device

No response

Refit Version

No response

Additional information ℹ️

No response

@infofromca infofromca added the bug label Aug 28, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant