private XDocument GetProductData <T>(IEnumerable <T> ids, string rangeFieldName)
            {
                CP.RetailTransactionServiceResponse serviceResponse = this.GetResponseFromMethod(
                    GetProductDataMethodName, string.Join(",", ids), 1, rangeFieldName);

                // Check result
                if (!serviceResponse.Success)
                {
                    throw new CommunicationException(
                              CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterTransactionServiceMethodCallFailure,
                              string.Format("Invoke method {0} failed: {1}", GetProductDataMethodName, serviceResponse.Message));
                }

                // Throw if service response does not contain any data.
                if (serviceResponse.Data == null || serviceResponse.Data.Length == 0)
                {
                    throw new CommunicationException(
                              CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterResponseParsingError,
                              "Service response does not contain any data.");
                }

                string productsXml = (string)serviceResponse.Data[0];

                object[] dataSource = (object[])serviceResponse.Data[1];
                var      dictionary = BuildDataSourceMap(dataSource);

                return(UpdateTableNamesWithDataSourceMap(productsXml, dictionary));
            }
            /// <summary>
            /// Gets the product search results using the specified category identifier.
            /// </summary>
            /// <param name="currentChannelId">The identifier of the channel that the request is originating from.</param>
            /// <param name="searchText">The search text that the result should be relevant to.</param>
            /// <param name="targetChannelId">The identifier of the channel to which the resultant product representatives must belong to.</param>
            /// <param name="targetCatalogId">The identifier of the catalog to which the resultant product representatives must belong to.</param>
            /// <param name="attributeIdCollectionString">The attribute values to retrieve along with the result set.</param>
            /// <param name="settings">The settings to use while processing this request.</param>
            /// <returns>A collection of product search results representing products in the requested category or its sub-categories.</returns>
            internal ReadOnlyCollection <ProductSearchResult> SearchProductsByText(long currentChannelId, string searchText, long targetChannelId, long targetCatalogId, string attributeIdCollectionString, QueryResultSettings settings)
            {
                CP.RetailTransactionServiceResponse transactionServiceResponse = this.GetResponseFromMethod(
                    GetProductsByKeywordMethodName,
                    currentChannelId,
                    searchText,
                    settings.Paging.Skip + 1,                                                                                                // 1-based in AX
                    settings.Paging.NumberOfRecordsToFetch,
                    settings.Sorting == null ? RecordIdAttributeName : settings.Sorting.ToString(),                                          // order by
                    settings.Sorting == null || !settings.Sorting.IsSpecified ? (settings.Sorting.Columns.First().IsDescending ? 1 : 0) : 0, // sort order: Ascending by default
                    false,                                                                                                                   // return total count
                    string.Empty,                                                                                                            // language
                    targetChannelId,
                    targetCatalogId,
                    attributeIdCollectionString);

                // Check result
                if (!transactionServiceResponse.Success)
                {
                    throw new CommunicationException(
                              CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterCommunicationFailure,
                              string.Format("Invoke method {0} failed: {1}", GetProductsByCategoryMethodName, transactionServiceResponse.Message));
                }

                // Throw if service response does not contain any data.
                if (transactionServiceResponse.Data == null || transactionServiceResponse.Data.Length == 0)
                {
                    throw new CommunicationException(CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterResponseParsingError, "Service response does not contain any data.");
                }

                string searchResultsXml = (string)transactionServiceResponse.Data[0];
                var    results          = this.GetResultsFromXml(searchResultsXml);

                return(results);
            }
Exemplo n.º 3
0
            /// <summary>
            /// Invokes transaction service health check.
            /// </summary>
            /// <returns>True if IsAlive call succeeded and false otherwise.</returns>
            public bool IsAlive()
            {
                TransactionServiceInvoker invoker =
                    (channel, info) => { return(channel.IsAlive(new CP.IsAlive()).result); };

                CP.RetailTransactionServiceResponse response = this.GetResponseFromMethod(invoker, IsAliveMethodName, 0);
                return(response.Success);
            }
            /// <summary>
            /// Gets the products using the specified category identifier.
            /// </summary>
            /// <param name="currentChannelId">The channel identifier of the current context.</param>
            /// <param name="targetChannelId">The channel identifier of the target channel.</param>
            /// <param name="targetCatalogId">The catalog identifier in the target channel.</param>
            /// <param name="targetCategoryId">The category identifier in the target channel.</param>
            /// <param name="skip">The number of records to skip.</param>
            /// <param name="top">The maximum number of records to return.</param>
            /// <param name="attributeIds">The comma-separated list of attribute record identifiers to retrieve. Specify '*' to retrieve all attributes.</param>
            /// <param name="includeProductsFromDescendantCategories">Whether category based product search should return products from all descendant categories.</param>
            /// <returns>A collection of products under the specified category.</returns>
            public ReadOnlyCollection <Product> GetProductsByCategory(
                long currentChannelId, long targetChannelId, long targetCatalogId, long targetCategoryId, long skip, long top, string attributeIds, bool includeProductsFromDescendantCategories)
            {
                if (currentChannelId <= 0)
                {
                    throw new ArgumentOutOfRangeException("currentChannelId", "The current channel identifier is required.");
                }

                if (skip < 0 || skip == int.MaxValue)
                {
                    throw new ArgumentOutOfRangeException("skip");
                }

                if (top < 0)
                {
                    throw new ArgumentOutOfRangeException("top", "The value must be a positive integer.");
                }

                ThrowIf.NullOrWhiteSpace(attributeIds, "attributeIds");

                CP.RetailTransactionServiceResponse serviceResponse = this.GetResponseFromMethod(
                    GetProductsByCategoryMethodName,
                    currentChannelId,
                    targetCategoryId,
                    skip + 1,     // 1-based in AX
                    top,
                    "ItemId",     // order by
                    1,            // sort order
                    false,        // return total count
                    string.Empty, // language
                    targetChannelId,
                    targetCatalogId,
                    attributeIds,
                    true,           // _includePrice
                    includeProductsFromDescendantCategories);

                // Check result
                if (!serviceResponse.Success)
                {
                    throw new CommunicationException(
                              CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterCommunicationFailure,
                              string.Format("Invoke method {0} failed: {1}", GetProductsByCategoryMethodName, serviceResponse.Message));
                }

                // Throw if service response does not contain any data.
                if (serviceResponse.Data == null || serviceResponse.Data.Length == 0)
                {
                    throw new CommunicationException(
                              CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterResponseParsingError,
                              "Service response does not contain any data.");
                }

                string productsXml = (string)serviceResponse.Data[0];
                var    products    = this.ConvertProductsXmlToProducts(productsXml);

                return(products);
            }
Exemplo n.º 5
0
            /// <summary>
            /// Invoke method with given method name and parameter list from AX without the check for null on the responding data.
            /// </summary>
            /// <param name="methodName">Method name.</param>
            /// <param name="parameters">The parameter set.</param>
            /// <returns>A list of returned items if available.</returns>
            /// <exception cref="CommunicationException">Throws if the call failed.</exception>
            private ReadOnlyCollection <object> InvokeMethodAllowNullResponse(string methodName, params object[] parameters)
            {
                ThrowIf.Null <string>(methodName, "methodName");

                CP.RetailTransactionServiceResponse serviceResponse = this.GetResponseFromMethod(methodName, parameters);

                if (serviceResponse == null)
                {
                    throw new CRT.CommunicationException(
                              CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterResponseParsingError,
                              "Service response is null.");
                }

                return(new ReadOnlyCollection <object>(serviceResponse.Data));
            }
Exemplo n.º 6
0
            /// <summary>
            /// Invoke extension method with given method name and parameter list from AX.
            /// </summary>
            /// <param name="methodName">Method name.</param>
            /// <param name="parameters">The parameter set.</param>
            /// <returns>A list of returned items if available.</returns>
            /// <exception cref="CommunicationException">Throws if the call failed.</exception>
            public ReadOnlyCollection <object> InvokeExtensionMethod(string methodName, params object[] parameters)
            {
                ThrowIf.Null <string>(methodName, "methodName");

                CP.RetailTransactionServiceResponse serviceResponse = this.GetResponseFromMethodEx(methodName, parameters);

                // Throw if service response does not contain any data.
                if (serviceResponse.Data == null || serviceResponse.Data.Length == 0)
                {
                    throw new CRT.CommunicationException(
                              CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterResponseParsingError,
                              "Service response does not contain any data.");
                }

                return(new ReadOnlyCollection <object>(serviceResponse.Data));
            }
Exemplo n.º 7
0
            /// <summary>
            /// Gets the response from method.
            /// </summary>
            /// <param name="transactionServiceInvoker">Delegate that invokes a specific operation on channel object.</param>
            /// <param name="methodName">Name of the method.</param>
            /// <param name="parameterCount">Number of parameters used during the call.  Used for instrumentation purposes.</param>
            /// <returns>The service response.</returns>
            private CP.RetailTransactionServiceResponse GetResponseFromMethod(TransactionServiceInvoker transactionServiceInvoker, string methodName, int parameterCount)
            {
                CP.RetailTransactionServiceResponse response = null;

                using (RealTimeServiceClientBoundaryPerfContext perfContext = new RealTimeServiceClientBoundaryPerfContext())
                {
                    Guid correlationId     = Guid.NewGuid();
                    Guid relatedActivityId = Guid.NewGuid();
                    RetailLogger.Log.CrtTransactionServiceClientRtsCallStarted(correlationId, methodName, parameterCount, relatedActivityId);
                    int    resultCount = -1;
                    string language    = null;
                    string company     = null;

                    CP.RetailRealTimeServiceContractChannel channel = null;
                    Exception exception = null;

                    try
                    {
                        channel = this.clientFactory.CreateTransactionServiceClient();

                        // Add HTTP header attribute named 'ms-dyn-aid' with value as activity id.
                        using (var contextScope = new OperationContextScope(channel))
                        {
                            this.SetActivityIdInHttpHeader(relatedActivityId);
                            CP.RetailTransactionServiceRequestInfo requestInfo = this.clientFactory.CreateRequestInfo();
                            company  = requestInfo.Company;
                            language = requestInfo.Language;
                            response = transactionServiceInvoker(channel, requestInfo);
                            channel.Close();
                        }
                    }
                    catch (System.ServiceModel.CommunicationException ex)
                    {
                        // Retrieves the SubCode in the fault exception, and maps them to corresponding error resources and diagnostic entries.
                        CommunicationErrors errorResourceId = CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterCommunicationFailure;
                        string errorMessage = string.Empty;
                        Tuple <string, string> faultCodes = TransactionServiceClient.ParseFaultException(ex);

                        if (faultCodes.Item2.Equals(TransactionServiceClient.FailedAuthenticationFaultCode, StringComparison.OrdinalIgnoreCase))
                        {
                            errorMessage = string.Format(
                                "Real-time Service call for method '{0}' failed due to security reason such as misconfigured, or expired Real-time Service certificate. Please also verify if the Real-time Service certificate is being properly configured in AX.",
                                methodName);
                            errorResourceId = CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_TransactionServiceAuthenticationFailedFault;
                        }
                        else if (faultCodes.Item2.Equals(TransactionServiceClient.ForbiddenFaultCode, StringComparison.OrdinalIgnoreCase))
                        {
                            errorMessage = string.Format(
                                "Real-time Service call for method '{0}' failed due to invalid Real-time Service profile settings. Please make sure the Real-time Service profile user and identity provider fields are defined correctly in AX.",
                                methodName);
                            errorResourceId = CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_TransactionServiceForbiddenFault;
                        }
                        else if (faultCodes.Item1.Equals(TransactionServiceClient.SenderFaultCode, StringComparison.OrdinalIgnoreCase))
                        {
                            errorMessage = string.Format(
                                "Real-time Service call for method '{0}' failed due to an unhandled exception, or due to invalid user permissions settings in Real-time Service profile. Please refer to the exception details for more information.",
                                methodName);
                            errorResourceId = CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_TransactionServiceSenderFault;
                        }

                        exception = TransactionServiceClient.CreateCommunicationException(methodName, ex, errorResourceId, errorMessage);
                    }
                    catch (SecurityTokenException ex)
                    {
                        // channel.Abort() will never throw
                        if (channel != null)
                        {
                            channel.Abort();
                        }

                        exception = TransactionServiceClient.CreateCommunicationException(methodName, ex, CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_HeadquarterCommunicationFailure);
                    }
                    catch (TimeoutException ex)
                    {
                        exception = TransactionServiceClient.CreateCommunicationException(methodName, ex, CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_TransactionServiceTimeOut);
                    }
                    catch (Exception ex)
                    {
                        // channel.Abort() will never throw
                        if (channel != null)
                        {
                            channel.Abort();
                        }

                        exception = TransactionServiceClient.CreateCommunicationException(methodName, ex, CommunicationErrors.Microsoft_Dynamics_Commerce_Runtime_TransactionServiceException);
                    }

                    // Throws an exception wrapping localized AX message for unsuccessful request.
                    if (exception == null && !response.Success)
                    {
                        exception = new HeadquarterTransactionServiceException(
                            response.Data,
                            string.Format("Real-time Service was successfully connected, but the method call {0} failed with this error : {1}", methodName, response.Message))
                        {
                            // Since content in the response.Message is already localized on AX, we copy it directly to user message field.
                            LocalizedMessage = response.Message
                        };
                    }
                    else if (response != null && response.Data != null)
                    {
                        resultCount = response.Data.Length;
                    }

                    if (exception != null)
                    {
                        RetailLogger.Log.CrtTransactionServiceClientRtsCallError(correlationId, methodName, parameterCount, language, company, exception.GetType().ToString(), exception, relatedActivityId);
                        throw exception;
                    }

                    perfContext.ResultsCount = resultCount;
                    perfContext.CallWasSuccessful();
                    RetailLogger.Log.CrtTransactionServiceClientRtsCallSuccessful(correlationId, methodName, parameterCount, resultCount, language, company, relatedActivityId);
                }

                return(response);
            }