Code Monkey home page Code Monkey logo

commercetools / commercetools-dotnet-core-sdk Goto Github PK

View Code? Open in Web Editor NEW
10.0 10.0 5.0 16.89 MB

The e-commerce SDK from commercetools running on the .NET Core platform

Home Page: https://docs.commercetools.com/sdk/dotnet-sdk#net-core-sdk

License: Apache License 2.0

C# 99.49% HTML 0.21% PowerShell 0.18% Ruby 0.07% CSS 0.05% JavaScript 0.01%
audit-sdk commercetools commercetools-dotnet-core-sdk commercetools-dotnet-sdk commercetools-sdk dotnet dotnet-core dotnet-standard sdk

commercetools-dotnet-core-sdk's People

Contributors

ashishhk avatar barbara79 avatar btastic avatar celeste-horgan avatar dependabot[bot] avatar hajoeichler avatar jenschude avatar jherey avatar jhumber avatar katstojanovski avatar michelerezk avatar purquhart avatar renovate-bot avatar sshibani avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

commercetools-dotnet-core-sdk's Issues

Write Integration tests for the remaining API domain models

Write Integration tests for the following API domain models:

  • Product Discounts
  • Cart Discounts
  • Product suggestions
  • Reviews
  • Tax category
  • Discound codes
  • Shopping list
  • Shipping methods
  • Shipping zones
  • Order imports
  • Product types
  • Types
  • Messages
  • Subscriptions
  • Stores
  • Channels
  • API Extensions

Missing InventoryEntryQuantitySet Message

It appears SDK is missing class for InventoryEntryQuantitySet message. Per commercetools documentation:

InventoryEntryQuantitySet Message

This message is the result of the update InventoryEntry with AddQuantity, RemoveQuantity or ChangeQuantity update action. In addition to the common Message fields, the InventoryEntryQuantitySet message contains the following fields:

type - String - "InventoryEntryQuantitySet"
oldQuantityOnStock - Number
newQuantityOnStock - Number
oldAvailableQuantity - Number
newAvailableQuantity - Number

OrderLine discountedPrice DTO mismatch

hi,

I'm trying to find the discountedPrice property in the SDK OrderLine DTO from the following json response of GET: /order/{id}

{
    "type": "Order",
....
    "lineItems": [
            "price": {
                "value": {
                    "type": "centPrecision",
                    "currencyCode": "USD",
                    "centAmount": 999,
                    "fractionDigits": 2
                },
                "id": "[REDACTED]"
            },
            "quantity": 1,
            "discountedPrice": {
                "value": {
                    "type": "centPrecision",
                    "currencyCode": "USD",
                    "centAmount": 899,
                    "fractionDigits": 2
                },
                "includedDiscounts": [
                    {
                        "discount": {
                            "typeId": "cart-discount",
                            "id": "[REDACTED]"
                        },
                        "discountedAmount": {
                            "type": "centPrecision",
                            "currencyCode": "USD",
                            "centAmount": 100,
                            "fractionDigits": 2
                        }
                    }
                ]
            },
....
   ]
....
}

While the SDK DTO only provide Price:

public class LineItem
  {
...
    public Price Price { get; set; }

    public TaxedItemPrice TaxedPrice { get; set; }

    public Money TotalPrice { get; set; }

    public List<DiscountedLineItemPriceForQuantity> DiscountedPricePerQuantity { get; set; }
...
  }

Price does include a Discount, however this is not set because it doesn't fit the JSON format.

ShipmentState & PaymentState should be optional / nullable on Order

The API documentation on order specifies that the shipmentState & paymentState are optional attributes on an order.
But in the current version of the SDK the corresponding fields (type=enum) on the order model are not nullable.
This results in a default value of ShipmentState.Shipped and PaymentState.BalanceDue being set on orders where the shipmentState or paymentState is not set (yet).

Let's make these fields nullable.

Parsing complex attributes fails with error

This is related to #131 but now for products that use a complex attribute.

I'm getting:

ย  Name Value Type
โ–ถ $exception {"Accessed JArray values with invalid key value: "key". Int32 array index expected."} System.ArgumentException
Newtonsoft.Json.dll!Newtonsoft.Json.Linq.JArray.this[object].get(object key)	Unknown
commercetools.Sdk.Serialization.dll!commercetools.Sdk.Serialization.LocalizedEnumConverter<commercetools.Sdk.Domain.Products.Attributes.Attribute, commercetools.Sdk.Domain.Products.Attributes.LocalizedEnumValue>.CanConvert(Newtonsoft.Json.Linq.JToken property) Line 21	C#
commercetools.Sdk.Serialization.dll!commercetools.Sdk.Serialization.MapperTypeRetriever<commercetools.Sdk.Domain.Products.Attributes.Attribute>.GetTypeForTokenFromMapper(Newtonsoft.Json.Linq.JToken token) Line 26	C#
commercetools.Sdk.Serialization.dll!commercetools.Sdk.Serialization.MapperTypeRetriever<commercetools.Sdk.Domain.Products.Attributes.Attribute>.GetTypeForToken(Newtonsoft.Json.Linq.JToken token) Line 19	C#
commercetools.Sdk.Serialization.dll!commercetools.Sdk.Serialization.SetMapperTypeRetriever<commercetools.Sdk.Domain.Products.Attributes.Attribute>.GetTypeForToken(Newtonsoft.Json.Linq.JToken token) Line 22	C#

commercetools.Sdk.Serialization.dll!commercetools.Sdk.Serialization.AttributeConverter.ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) Line 37 C#

jsonObject inside AttributeConverter.ReadJson:

{
  "name": "printmethod",
  "value": [
    [
      {
        "value": "25 x 10",
        "name": "size"
      },
      {
        "value": "P1",
        "name": "id"
      },
      {
        "value": {
          "nl": "**"
        },
        "name": "name"
      },
      {
        "value": {
          "nl": "Wtte Dop"
        },
        "name": "displaylabel"
      }
    ],
    [
      {
        "value": "25cx",
        "name": "size"
      },
      {
        "value": "P1",
        "name": "id"
      },
      {
        "value": {
          "nl": "Bottle"
        },
        "name": "displaylabel"
      },
      {
        "value": {
          "nl": "pmm"
        },
        "name": "name"
      }
    ]
  ]
}

Unable to resolve service for type 'IClientConfiguration' while attempting to activate 'ApiExceptionFactory'

Hello,

just fiddling around with the this library and just found the first exception..

image

Just configuring it as per the readme file gives me the following error:

InvalidOperationException: Unable to resolve service for type 'commercetools.Sdk.HttpApi.IClientConfiguration' while attempting to activate 'commercetools.Sdk.HttpApi.ApiExceptionFactory'.

I had a look at the code and it seems that you never register the IClientConfiguration as a singleton.

Sorting by ID does not work when querying Messages.Message

Hi,

I'm writing a piece of integration software where we need to pull all changes on Customers and Orders. We need to use the ID into a compound sort statement within the QueryCommand to make the result deterministic, for example (CreatedAt, Name, ID). However I found out that sorting on ID does not work when used as primary sorting key.
I am using a master build from 4-10-2019
thanks,
pepijn

Authentication fails on "scope" (vs "projectscope")

Hi,

I'm using CommerceTools authentication URL:
https://auth.sphere.io/oauth/token?grant_type=client_credentials&scope=ManageProject
With basic authentication.
However when using the SDK and Postman, I get a 400 back:

{
    "statusCode": 400,
    "message": "Malformed parameter: scope: Invalid scope.",
    "errors": [
        {
            "code": "invalid_scope",
            "message": "Malformed parameter: scope: Invalid scope."
        }
    ],
    "error": "invalid_scope",
    "error_description": "Malformed parameter: scope: Invalid scope."
}

When performing the query in Postman with projectscope instead of scope, I get back a valid response.

Querying with datetimes does not have quotes / correct format

Given the following test case:

[Fact]
public void ExpressionWithDateTimeFilters()
{
    DateTime startDate = new DateTime(2020, 11, 21);
    DateTime endDate = startDate.AddMonths(1);

    Expression<Func<Order, bool>> expression = x => x.CreatedAt >= startDate && x.CreatedAt <= endDate;
    IQueryPredicateExpressionVisitor queryPredicateExpressionVisitor = this.linqFixture.GetService<IQueryPredicateExpressionVisitor>();
    string result = queryPredicateExpressionVisitor.Render(expression);
    Assert.Equal("createdAt >= \"2020-11-21\" and createdAt <= \"2020-12-21\"", result);
}

Produces the following outcome:
image

Getting a customer by email address

I am attempting to get a customer by email address from commercetools using a Query Predicate. The search is case-sensitive. For example if CT contains "[email protected]" and I pass "[email protected]" then I do not get a result. How to the search to be case-insensitive? See example below. Thank you.

QueryCommand command = new QueryCommand();
QueryPredicate predicate = new QueryPredicate(c => c.Email == email);
command.SetWhere(predicate);
PagedQueryResult response = await _client.ExecuteAsync(command);

Using TokenProvider.Token from within a test context causes deadlock

Hi ๐Ÿ‘‹ Just a quick one...

I'm trying to get an anonymous token to pass back to the user from within an API. I am setting everything up as expected in the readme and realised that I can actually resolve the collection of TokenProviders directly in order to get an anonymous token.

My source code...

public AnonymousTokenProvider(IEnumerable<ITokenProvider> tokenProviders)
{
    _tokenProvider = tokenProviders.First(tp => tp.TokenFlow == TokenFlow.AnonymousSession);
}

public Task<Token> GetToken()
{
    var token = _tokenProvider.Token;
    return Task.FromResult(token);
}

I have an integration test that invokes this class which works fine when it runs on its own but fails when it runs with other tests in parallel. I think we're hitting an async/await deadlocking issue here because _tokenProvider.Token is invoking an async call and calling .Result on the task.

I'm fairly certain this is the cause of my issue because when I inline the code from this repo but make it async all the way it solves my locking issue.

Is there a reason why this can't be replaced with an async method call instead? Would anyone mind if I submit a PR to fix this?

Thanks! ๐Ÿ‘

DiscountCodeState has a wrong value

The DiscountCodeState.DoesNotMatch enum value does not match the API (as the documentation explains). This leads to a deserialization error of the JSON response from Commerce Tools when a Discount Code does not match the Cart in which it has been applied. Based on that, the correct value should be DoesNotMatchCart.

The actual code is

public enum DiscountCodeState
  {
    NotActive,
    NotValid,
    DoesNotMatch,
    MatchesCart,
    MaxApplicationReached,
    ApplicationStoppedByPreviousDiscount,
  }

Plans on ditching Newtonsoft.Json in favour of new System.Text.Json serializer

Hello,

are there any plans of ditching Newtonsoft.Json in favour of System.Text.Json serializer? We are currently rewriting our business applications to use .NET Core 3.0. When returning commercetools responses we have problems when serializing commercetools objects, as they are usually JObjects and so on. System.Text.Json has problems with that. When everyone uses System.Text.Json this would not be a problem.

So.. are there any plans on that?

Where clause with "in" and arrays and lists creates a bad request

Given the following test cases:

[Fact]
public void ExpressionWhereInString()
{
    string[] orderNumbers = { "5", "10", "15" };
    Expression<Func<Order, bool>> expression = x => x.OrderNumber.In(orderNumbers);
    IQueryPredicateExpressionVisitor queryPredicateExpressionVisitor = this.linqFixture.GetService<IQueryPredicateExpressionVisitor>();
    string result = queryPredicateExpressionVisitor.Render(expression);
    Assert.Equal("orderNumber in (\"5\", \"10\", \"15\")", result);
}

Outputs the following:
image

[Fact]
public void ExpressionWhereInStringList()
{
    List<string> orderNumbers = new List<string>(){ "5", "10", "15" };
    Expression<Func<Order, bool>> expression = x => x.OrderNumber.In(orderNumbers.ToArray());
    IQueryPredicateExpressionVisitor queryPredicateExpressionVisitor = this.linqFixture.GetService<IQueryPredicateExpressionVisitor>();
    string result = queryPredicateExpressionVisitor.Render(expression);
    Assert.Equal("orderNumber in (\"5\", \"10\", \"15\")", result);
}

Outputs the following:
image

From what I analyzed, it seems that the ConstantPredicateVisitorConverter is not the right job for arrays/collections. I tried implementing a InMethodPredicateVisitorConverter which seems to do a similar thing when filtering, but there are some bits that I don't know :/

If you need anything, shoot me an email @jenschude

Where-In queries with enum-arrays will generate bad requests

Given the following test cases:

[Fact]
public void ExpressionEnumWhereInList()
{
    List<OrderState> orderStates = new[] { OrderState.Open, OrderState.Complete, OrderState.Confirmed }.ToList();
    Expression<Func<Order, bool>> expression = x => x.OrderState.In(orderStates);
    IQueryPredicateExpressionVisitor queryPredicateExpressionVisitor = this.linqFixture.GetService<IQueryPredicateExpressionVisitor>();
    string result = queryPredicateExpressionVisitor.Render(expression);
    Assert.Equal("orderState in (\"Open\", \"Complete\", \"Confirmed\")", result);
}

[Fact]
public void ExpressionEnumWhereInListValueOf()
{
    List<OrderState> orderStates = new[] { OrderState.Open.valueOf(), OrderState.Complete.valueOf(), OrderState.Confirmed.valueOf() }.ToList();
    Expression<Func<Order, bool>> expression = x => x.OrderState.In(orderStates);
    IQueryPredicateExpressionVisitor queryPredicateExpressionVisitor = this.linqFixture.GetService<IQueryPredicateExpressionVisitor>();
    string result = queryPredicateExpressionVisitor.Render(expression);
    Assert.Equal("orderState in (\"Open\", \"Complete\", \"Confirmed\")", result);
}

[Fact]
public void ExpressionEnumWhereInArray()
{
    OrderState[] orderStates = new[] { OrderState.Open, OrderState.Complete, OrderState.Confirmed };
    Expression<Func<Order, bool>> expression = x => x.OrderState.In(orderStates);
    IQueryPredicateExpressionVisitor queryPredicateExpressionVisitor = this.linqFixture.GetService<IQueryPredicateExpressionVisitor>();
    string result = queryPredicateExpressionVisitor.Render(expression);
    Assert.Equal("orderState in (\"Open\", \"Complete\", \"Confirmed\")", result);
}

[Fact]
public void ExpressionEnumWhereInArrayValueOf()
{
    OrderState[] orderStates = new[] { OrderState.Open.valueOf(), OrderState.Complete.valueOf(), OrderState.Confirmed.valueOf() };
    Expression<Func<Order, bool>> expression = x => x.OrderState.In(orderStates);
    IQueryPredicateExpressionVisitor queryPredicateExpressionVisitor = this.linqFixture.GetService<IQueryPredicateExpressionVisitor>();
    string result = queryPredicateExpressionVisitor.Render(expression);
    Assert.Equal("orderState in (\"Open\", \"Complete\", \"Confirmed\")", result);
}

The tests will all fail with something like this:

image

I already provided a fix, I don't know if this is the right way, but the tests won't fail, and our internal application tests also like this fix.

Query'ing objects with Where predicate doesn't work

Serializing the following Where predicates don't produce a valid where query.

_client.Query<Product>().Where(x => x.MasterData.Published);
_client.Query<Product>().Where(x => !x.MasterData.Published);

They respectively create the following where query:

where=masterdata(published)
where=not(masterdata(published))

Both where queries are invalid and let the HTTP API return an error message of a malformed where parameter.
While it would be a nice addition to the HTTP API to support those syntax too, the current code would do best to make up for that slight too.

I created a PR with changes, serializing the above Where predicates into the following where queries respectively, which yields the correct data from the API:

where=masterdata(published = true)
where=masterdata(published = false)

kick off auto-generate dotnet core sdk

Kick off Generated Dotnet Core SDK kick off.

Acceptance criteria:

  • Schedule a meeting for kick off of generated SDK for dotnet core.
  • List down what is required and plan the execution. here
  • Start with Dotnet Core SDK Generation

Token Refresh

After the token is expired (2dys) the token is not refreshed by the SDK. restarting the app resolve the issue. see below exception details:

2019-03-25 08:32:05.786 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request starting HTTP/1.1 GET http://sl-apifacade-rnd-api.azurewebsites.net/api/Product/GetOutboundRoute?arrivalCountry=denmark  
2019-03-25 08:32:05.865 +00:00 [Information] Microsoft.AspNetCore.Routing.EndpointMiddleware: Executing endpoint ' .APIFacade.Controllers.ProductController.GetOutboundRouteAsync ( .APIFacade)'
2019-03-25 08:32:05.905 +00:00 [Information] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker: Route matched with {action = "GetOutboundRouteAsync", controller = "Product"}. Executing action  .APIFacade.Controllers.ProductController.GetOutboundRouteAsync ( .APIFacade)
2019-03-25 08:32:05.932 +00:00 [Information] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker: Executing action method  .APIFacade.Controllers.ProductController.GetOutboundRouteAsync ( .APIFacade) with arguments (denmark) - Validation state: Valid
2019-03-25 08:32:05.991 +00:00 [Information] System.Net.Http.HttpClient.APIFacadeCommerceToolsClient.LogicalHandler: Start processing HTTP request POST https://api.sphere.io/dc-poc/product-projections/search
2019-03-25 08:32:05.991 +00:00 [Information] LoggerHandler: https://api.sphere.io/dc-poc/product-projections/search
2019-03-25 08:32:05.992 +00:00 [Information] LoggerHandler: POST
2019-03-25 08:32:05.992 +00:00 [Information] LoggerHandler: dc-poc/5a765025-b32d-4d1c-8860-85e8998529bc
2019-03-25 08:32:05.992 +00:00 [Information] System.Net.Http.HttpClient.APIFacadeCommerceToolsClient.ClientHandler: Sending HTTP request POST https://api.sphere.io/dc-poc/product-projections/search
2019-03-25 08:32:06.040 +00:00 [Information] System.Net.Http.HttpClient.APIFacadeCommerceToolsClient.ClientHandler: Received HTTP response after 37.2564ms - Unauthorized
2019-03-25 08:32:06.080 +00:00 [Information] Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker: Executed action  .APIFacade.Controllers.ProductController.GetOutboundRouteAsync ( .APIFacade) in 164.1591ms
2019-03-25 08:32:06.081 +00:00 [Information] Microsoft.AspNetCore.Routing.EndpointMiddleware: Executed endpoint ' .APIFacade.Controllers.ProductController.GetOutboundRouteAsync ( .APIFacade)'
2019-03-25 08:32:06.177 +00:00 [Error] Microsoft.AspNetCore.Server.Kestrel: Connection id "0HLLES49IDD5K", Request id "0HLLES49IDD5K:00000004": An unhandled exception was thrown by the application.
commercetools.Sdk.HttpApi.Domain.Exceptions.InvalidTokenException: Request Summary: POST https://api.sphere.io/dc-poc/product-projections/search failed Unauthorized with X-Correlation-ID 'dc-poc/5a765025-b32d-4d1c-8860-85e8998529bc' on 2019-03-25T08:32:06
Response: {"statusCode":401,"message":"invalid_token","errors":[{"code":"invalid_token","message":"invalid_token"}],"error":"invalid_token"}
project: dc-poc
   at commercetools.Sdk.HttpApi.DelegatingHandlers.ErrorHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in C:\Work\Bridging\ \CommerceToolsSDK\dotnet-core\commercetools.Sdk.HttpApi\DelegatingHandlers\ErrorHandler.cs:line 27
   at commercetools.Sdk.HttpApi.DelegatingHandlers.LoggerHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in C:\Work\Bridging\ \CommerceToolsSDK\dotnet-core\commercetools.Sdk.HttpApi\DelegatingHandlers\LoggerHandler.cs:line 29
   at commercetools.Sdk.HttpApi.DelegatingHandlers.CorrelationIdHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in C:\Work\Bridging\ \CommerceToolsSDK\dotnet-core\commercetools.Sdk.HttpApi\DelegatingHandlers\CorrelationIdHandler.cs:line 20
   at commercetools.Sdk.HttpApi.DelegatingHandlers.AuthorizationHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) in C:\Work\Bridging\ \CommerceToolsSDK\dotnet-core\commercetools.Sdk.HttpApi\DelegatingHandlers\AuthorizationHandler.cs:line 25
   at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at commercetools.Sdk.HttpApi.Client.SendRequest[T](HttpRequestMessage requestMessage) in C:\Work\Bridging\ \CommerceToolsSDK\dotnet-core\commercetools.Sdk.HttpApi\Client.cs:line 48
   at commercetools.Sdk.HttpApi.Client.ExecuteAsync[T](Command`1 command)
   at  .APIFacade.Controllers.ProductController.GetOutboundRouteAsync(String arrivalCountry) in C:\Work\Bridging\ \ .APIFacade\Controllers\ProductController.cs:line 35
   at lambda_method(Closure , Object )
   at Microsoft.Extensions.Internal.ObjectMethodExecutorAwaitable.Awaiter.GetResult()
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.AwaitableObjectResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeNextResourceFilter()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Rethrow(ResourceExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Routing.EndpointMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Routing.EndpointRoutingMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Server.IISIntegration.IISMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Server.Kestrel.Core.Internal.Http.HttpProtocol.ProcessRequests[TContext](IHttpApplication`1 application)
2019-03-25 08:32:06.217 +00:00 [Information] Microsoft.AspNetCore.Hosting.Internal.WebHost: Request finished in 480.9585ms 500 

Mobile app Demo for Dotnet CORE SDK

Mobile app Demo development for Dotnet CORE SDK

  • Implement Cart Feature, create cart, add product to cart, anonymous cart creation

Timebox : 1 week.

Create a change log

What?

Create a change log

Why?

So that users can see what was changed and can find breaking changes

Acceptance criteria:

  • User can see see changes

Multiple Skip and Take won't have expected effect

Currently both extensions SearchProducts and Query won't handle multiple Skip and Take operations as expected from LinQ.

The following lines (regardless of how uncommon they might be) will result in wrong limits and offsets:

query.Take(3).Skip(1).Take(4);  // that should yield 2 items from offset 1
query.Skip(4).Take(3).Skip(1);  // that should yield 3 items from offset 5
query.Take(3).Skip(2);          // that should yield 1 item from offset 2

They result in the following outputs respectively:

?offset=1&limit=4
?offset=1&limit=3
?offset=2&limit=3

Given the above LinQ query though, the results should be the following respectively:

?offset=1&limit=2
?offset=5&limit=3
?offset=2&limit=1

The made PR fixes the mentioned issue by adding appropriate logic to the "Take" and "Skip" cases in ClientQueryProvider and the Offset and Limit extensions on SearchProductProjectionsCommand.

JsonSerializationException is thrown when no icu-libs are installed on Docker image

I just switched a service from using commercetools.NET.SDK to commercetools.Sdk.All.
All is working fine locally.
My service is shipped using dotnet:2.2-aspnetcore-runtime-alpine Docker image.
When running the service inside the container it throws a JsonSerializationException without any errormessage:

Newtonsoft.Json.JsonSerializationException: Exception of type 'Newtonsoft.Json.JsonSerializationException' was thrown.
   at commercetools.Sdk.Serialization.AttributeConverter.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(JsonConverter converter, JsonReader reader, Type objectType, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(IList list, JsonReader reader, JsonArrayContract contract, JsonProperty containerProperty, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, Object existingValue, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
   at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Deserialize(JsonReader reader, Type objectType)
   at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)\n   at commercetools.Sdk.Serialization.SerializerService.Deserialize[T](String input)
   at commercetools.Sdk.HttpApi.CtpClient.SendRequest[T](HttpRequestMessage requestMessage)
   at commercetools.Sdk.HttpApi.CtpClient.ExecuteAsync[T](Command`1 command)
   at ProductService.Repository.CommerceToolsProductsRepository.<>c__DisplayClass23_0.<<FetchProducts>b__0>d.MoveNext() in /app/ProductService/Repository/CommerceToolsProductsRepository.cs:line 242\n--- End of stack trace from previous location where exception was thrown ---\n   at ...

After lots of investigation I figured out that this is due to the fact that International Components for Unicode library (a.k.a. icu-libs) is missing in dotnet:2.2-aspnetcore-runtime-alpine.
Adding the icu-libs:

FROM microsoft/dotnet:2.2-aspnetcore-runtime-alpine
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false
RUN apk add --no-cache icu-libs
ENV LC_ALL en_US.UTF-8
ENV LANG en_US.UTF-8

I believe the error being thrown could be more descriptive about the actual problem. Please have this one fixed, for other developers bumping into this problem.

Empty attribute value array throws exception

I don't know if it should even happen for the returned attributes to contain of an empty array in the value object, but it did happen.

If the value object of an attribute is an empty array, the SetMapperTypeReceiver<T> can't determine an appropriate type for that array and returns null, which down the line will cause the AttributeConverter to throw a JsonSerializationExcpetion with no error message whatsoever. (Refer to L38-41 in the AttributeConverter).

To circumvent this case, I made a PR, which adds a special check if the given value is an empty JSON array and will return the type object. Since the array isn't rly deserialized much, since it doesn't contain elements, the object type shouldn't cause any side effects in those cases.

After that, the yielded data was fully deserializable by the rest of the pipeline and ready to use in our business logic.

Omit scopes from the get token query when they are empty

Hi ๐Ÿ™Œ

My understanding of the way the API works is that if no scopes are specified when requesting access tokens then the default set of scopes for that API client are returned.

Currently in the AnonymousSessionTokenProvider it adds the scopes query whether the scopes are present in the configuration or not.

Can we change this to be something more like this?

HttpRequestMessage request = new HttpRequestMessage();
            string requestUri = this.ClientConfiguration.AuthorizationBaseAddress + $"oauth/{this.ClientConfiguration.ProjectKey}/anonymous/token?grant_type=client_credentials";
            if(string.IsNullOrEmpty(this.ClientConfiguration.Scope))
            {
                requestUri += $"&scope={this.ClientConfiguration.Scope}";
            }
            if (!string.IsNullOrEmpty(this.anonymousCredentialsStoreManager.AnonymousId))
            {
                requestUri += $"&anonymous_id={this.anonymousCredentialsStoreManager.AnonymousId}";
            }

Thanks! ๐Ÿ˜„

Query Case Sensitive

Hi,
I have a question:
Is it possible to make a query case insensitive?
command.Where("custom(fields(lastName="" + exampleName+ ""))");
And get result for both variants: exampleName and ExampleName

Custom services Documentation

Acceptance criteria

  • documentation for customization is in README
  • We as a team agree that the documentation is sufficient

Setup multiple clients with different configurations

Hello, we are currently migrating to the new library. We are using the SDK to create CtpClients (or Client in the old version) different types of clients using different projects.

This is used in a multi-tenancy setup where different customers have different needs but we only have one backend to handle the requests.

Right now I don't see a way to setup multiple clients with different configurations (project key, client secrets and so on).

Can you point me in a direction what I need to do?

attribute type fails to deserialize

When the json parser encounters:

"type": {
            "name": "set",
            "elementType": {
              "name": "nested",
              "typeReference": {
                "typeId": "product-type",
                "id": "5596962f-3969-4d16-838b-df0b598b4971"
              }
            }
          },

It fails on "name": "nested" with this error:

โ–ถ | $exception | {"Couldn't get type to deserialize property name"} |

What can I do to make this work?

Callstack:

>	commercetools.Sdk.Serialization.dll!commercetools.Sdk.Serialization.JsonConverterDecoratorTypeRetrieverBase<commercetools.Sdk.Domain.AttributeType>.ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) Line 45	C#
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(Newtonsoft.Json.JsonConverter converter, Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonConverter propertyConverter, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, Newtonsoft.Json.JsonReader reader, object target)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, string id)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(Newtonsoft.Json.JsonReader reader, System.Type objectType, bool checkAdditionalContent)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerProxy.DeserializeInternal(Newtonsoft.Json.JsonReader reader, System.Type objectType)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.JsonSerializer.Deserialize(Newtonsoft.Json.JsonReader reader, System.Type objectType)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Linq.JToken.ToObject(System.Type objectType, Newtonsoft.Json.JsonSerializer jsonSerializer)	Unknown
 	commercetools.Sdk.Serialization.dll!commercetools.Sdk.Serialization.JsonConverterDecoratorTypeRetrieverBase<commercetools.Sdk.Domain.AttributeType>.ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer) Line 45	C#
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.DeserializeConvertable(Newtonsoft.Json.JsonConverter converter, Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonConverter propertyConverter, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, Newtonsoft.Json.JsonReader reader, object target)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, string id)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(System.Collections.IList list, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonArrayContract contract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, string id)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, object existingValue, string id)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonConverter propertyConverter, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, Newtonsoft.Json.JsonReader reader, object target)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, string id)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateList(System.Collections.IList list, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonArrayContract contract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, string id)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateList(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, object existingValue, string id)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(Newtonsoft.Json.Serialization.JsonProperty property, Newtonsoft.Json.JsonConverter propertyConverter, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty, Newtonsoft.Json.JsonReader reader, object target)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(object newObject, Newtonsoft.Json.JsonReader reader, Newtonsoft.Json.Serialization.JsonObjectContract contract, Newtonsoft.Json.Serialization.JsonProperty member, string id)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateValueInternal(Newtonsoft.Json.JsonReader reader, System.Type objectType, Newtonsoft.Json.Serialization.JsonContract contract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerMember, object existingValue)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(Newtonsoft.Json.JsonReader reader, System.Type objectType, bool checkAdditionalContent)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.JsonSerializer.DeserializeInternal(Newtonsoft.Json.JsonReader reader, System.Type objectType)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.JsonSerializer.Deserialize(Newtonsoft.Json.JsonReader reader, System.Type objectType)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.JsonConvert.DeserializeObject(string value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings)	Unknown
 	Newtonsoft.Json.dll!Newtonsoft.Json.JsonConvert.DeserializeObject<commercetools.Sdk.Domain.PagedQueryResult<commercetools.Sdk.Domain.ProductType>>(string value, Newtonsoft.Json.JsonSerializerSettings settings)	Unknown
 	commercetools.Sdk.Serialization.dll!commercetools.Sdk.Serialization.SerializerService.Deserialize<commercetools.Sdk.Domain.PagedQueryResult<commercetools.Sdk.Domain.ProductType>>(string input) Line 21	C#
 	commercetools.Sdk.HttpApi.dll!commercetools.Sdk.HttpApi.CtpClient.SendRequest<commercetools.Sdk.Domain.PagedQueryResult<commercetools.Sdk.Domain.ProductType>>(System.Net.Http.HttpRequestMessage requestMessage) Line 58	C#

Full attribute info:

{
  "limit": 500,
  "offset": 0,
  "count": 2,
  "results": [
    {
      "id": "5596962f-3969-4d16-838b-df0b598b4971",
      "version": 1,
      "createdAt": "2020-06-11T12:11:24.201Z",
      "lastModifiedAt": "2020-06-11T12:11:24.201Z",
      "name": "name",
      "description": "",
      "classifier": "Complex",
      "attributes": [
        {
          "name": "id",
          "label": {
            "de": "id",
            "nl": "id"
          },
          "inputTip": {
            "de": "",
            "nl": ""
          },
          "isRequired": true,
          "type": { "name": "text" },
          "attributeConstraint": "SameForAll",
          "isSearchable": true,
          "inputHint": "SingleLine",
          "displayGroup": "Other"
        },
        {
          "name": "name",
          "label": {
            "de": "",
            "nl": "naam"
          },
          "inputTip": {
            "de": "",
            "nl": ""
          },
          "isRequired": true,
          "type": { "name": "ltext" },
          "attributeConstraint": "SameForAll",
          "isSearchable": false,
          "inputHint": "SingleLine",
          "displayGroup": "Other"
        },
        {
          "name": "size",
          "label": {
            "de": "",
            "nl": "grootte"
          },
          "inputTip": {
            "de": "",
            "nl": ""
          },
          "isRequired": false,
          "type": { "name": "text" },
          "attributeConstraint": "SameForAll",
          "isSearchable": false,
          "inputHint": "SingleLine",
          "displayGroup": "Other"
        },
        {
          "name": "displaylabel",
          "label": {
            "de": "",
            "nl": "Label"
          },
          "inputTip": {
            "de": "",
            "nl": ""
          },
          "isRequired": false,
          "type": { "name": "ltext" },
          "attributeConstraint": "SameForAll",
          "isSearchable": false,
          "inputHint": "SingleLine",
          "displayGroup": "Other"
        }
      ],
      "key": "pp"
    },
    {
      "id": "588bac60-38b0-40dc-ab52-db152f6b3dcd",
      "version": 3,
      "createdAt": "2020-06-11T12:11:24.215Z",
      "lastModifiedAt": "2020-06-11T12:13:43.168Z",
      "name": "productdata",
      "description": "",
      "classifier": "Complex",
      "attributes": [
        {
          "name": "primary_cat",
          "label": {
            "de": "",
            "nl": "Hoofd category"
          },
          "inputTip": {
            "de": "",
            "nl": ""
          },
          "isRequired": false,
          "type": {
            "name": "reference",
            "referenceTypeId": "category"
          },
          "attributeConstraint": "SameForAll",
          "isSearchable": true,
          "inputHint": "SingleLine",
          "displayGroup": "Other"
        },
        {
          "name": "printMethods",
          "label": {
            "nl": "Print methode",
            "en": "print method"
          },
          "isRequired": false,
          "type": {
            "name": "set",
            "elementType": {
              "name": "nested",
              "typeReference": {
                "typeId": "product-type",
                "id": "5596962f-3969-4d16-838b-df0b598b4971"
              }
            }
          },
          "attributeConstraint": "SameForAll",
          "isSearchable": true,
          "inputHint": "SingleLine",
          "displayGroup": "Other"
        }
      ],
      "key": "productdata"
    }
  ]
}

Question about Creating a Customer

The code listed below creates customer in commercetools but the customer object is not initialized. This is because the Create Customer method in commertools returns a CustomerSignInResult object and not a Customer object. How do I get the CustomerSignInResult response using the SDK?

CreateCommand command = new CreateCommand(customerDraft);
Customer customer = client.ExecuteAsync(command).Result;

Where clause with enum field creates a bad request

I created a simple test case for this:

public void ExpressionEvaluationWithEnumsFails()
{
    OrderState orderState = OrderState.Open;
    Expression<Func<Order, bool>> expression = x => x.OrderState == orderState;
    IQueryPredicateExpressionVisitor queryPredicateExpressionVisitor = this.linqFixture.GetService<IQueryPredicateExpressionVisitor>();
    string result = queryPredicateExpressionVisitor.Render(expression);
    Assert.Equal("orderState = \"open\"", result);
}

Test result:
image

Fiddler shows the same:
image

commercetools documentation on how to query:
https://docs.commercetools.com/http-api-query-predicates#query-predicate-examples

Using valueOf() does not work this time around.

Migrate Integration tests

Migrate Integration tests for the following API domain models:

  • Customers
  • CustomerGroups
  • Category
  • Payments
  • States
  • Projects
  • Errors
  • GraphQL
  • CustomObjects
  • Products
  • ProductProjections
  • ProductDiscounts
  • Inventory
  • Carts
  • Orders
  • ProductProjectionSearch

Exception getting cart discount

When there is a Cart Discount in commercetools with "Multibuy line items" selected, I get an exception retrieving cart discounts

Sample Code

QueryCommand command = new QueryCommand();
PagedQueryResult response = await client.ExecuteAsync(command);

Exception

The exception occurs in SDK in ReadJson function in JsonConverterDecoratorTypeRetrieverBase.cs file.

System.AggregateException: One or more errors occurred. (Couldn't get type to deserialize property type)
---> Newtonsoft.Json.JsonSerializationException: Couldn't get type to deserialize property type
at commercetools.Sdk.Serialization.JsonConverterDecoratorTypeRetrieverBase`1.ReadJson(JsonReader reader, Type objectType, Object existingValue, JsonSerializer serializer)

CT2
CT1
JsonConverterDecoratorTypeRetrieverBase

Remove legacy hostname

Description

To improve the developer experience and easen our support and training burden all existing references to *.sphere.io and .commercetools.co host names should be removed in favor of not defaulting to a specific region (a common complaint of US and AWS customers is that EU is defaulted everywhere) or, if needed for backwards compatibility, be replaced with the new *.europe-west1.gcp.commercetools.com notation.

Expected Behavior

full text search over the repository for ".sphere.io" and ".commercetools.co" should yield zero results

Context

https://docs.commercetools.com/release-notes#releases-2020-02-03-aws-and-new-hostnames

Query with Nested Custom Fields

Hi,

I have the following problem:

Task: get Customer, that has KupCustomerNumber nested in custom field Adresses->AdditionalAddressInfo (This is field contains custom Object).

Solution:
In normal situation for retrieving Customer we could use lambda expression like:
command.Where(s => s.Addresses.Any(m => m.AdditionalAddressInfo.Contains("CustomerNo:" + customer.KuPCustomerNo + """)));

Could you please say me if that possible to do with your current solution like:
command.Where("custom(fields(Addresses(AdditionalAddressInfo(CustomerNo ="" + customer.KuPCustomerNo + ""))");

Thanks!

Order Get Custom Fields

Hi,

I am trying to use your package in order to work wirh Orders from Merchant Center.

In my VS code I try to work with custom Fields like "KupCustomerNumber" or "AbAccountBusinessPartnerId".
Code Example:
var resultQuery = await _client.ExecuteAsync(command.Where(c => (string)c.Custom.Fields["KupCustomerNumber"]== "xxxxxx|")):

Problem: while executing the above code line, the field "KupCustomerNumber" will be converted in "kupCustomerNumber" (in lower case)! Like that;

custom(fields(kupCustomerNumber="xxxxxx"))

Of course, the returned result is null because of name of custom field.

Query'ing without any Take or Skip restriction only loads first page

Using client.Query<T>() one will only receive the default 20 items from the first page. If we want to get more than that or all items of the given T, then we are bound to Skip and Take ourselves in a loop.
This approach however has one major flaw. Before the first execution of the query, you basically have no idea how many items you have in total, nor does the Query<T>() extension return the total value if Queryparameter withTotal=true.

A solution to that would be a client.QueryAll<T>() extension in addition to an appropriate enumerator for that case.
The enumerator will keep track of the current page items and retrieves new ones, if the page is exhausted.

Example:

var productQuery = client.QueryAll<Product>().Where(x => x.MasterData.Published);
foreach(var product in productQuery)
{
    ;  // Do things with the product
}

As you can see, the syntax would be nearly the same, while providing all items of a requested type on demand. So it will also not flood the machines memory with all the requested items at once.

MaxApplications and MaxApplicationsPerCustomer initialized to 0 by default

When creating a DiscountCodeDraft class and not setting MaxApplications or MaxApplicationsPerCustomer properties, these values (which are optional according to documentation) are sent through the API set as 0.
If you then try to apply the given code, the code cannot be applied due to MaxApplicationReached error.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.