0

I am currently developing a dll in .Net 4.7.1 that consumes an API Rest, while developing and testing the postAsync method works perfectly and consumes the endpoint, however when deploying the dll to the client app on a server, it shows "An error ocurred while sending the request", the Inner Exception that is shown is expecting element 'root' from namespace ''.. encountered 'none' with name '' namespace ''

It works perfectly while I am consuming the API from my local computer, I even tried with Postman on the client server and it connected successfully to the endpoint, I also tried running the dll with an app that simulates the client app and it worked as expected on both my computer and the server, the error is only shown only when the actual client calls the dll and tries to consume the API.

Hopefully the explanation was clear enough, here is the code that is used to call the API:

public static class Api
{
        public static async Task<ApiResponse> RunPaymentAsync(PaymentRequest paymentRequest, Account account)
        {
                HttpClient client = new HttpClient();
                client.Timeout = TimeSpan.FromMinutes(1.2);
                client.DefaultRequestHeaders.ProxyAuthorization = null;
                client.BaseAddress = new Uri(ApiUri); // I am unable to provide the actual URL of the API 
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                ProductRequest request = new ProductRequest()
                {
                        Id = paymentRequest.Id,
                        Client = account.creditorAccount
                        /* More info of the product and client */ 
                };

            var jsonRequest = JSONSerializer<ProductRequest>.Serialize(request);

            var requestBuffer = Encoding.UTF8.GetBytes(jsonRequest);

            var byteContent = new ByteArrayContent(requestBuffer);

            byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");

            ApiResponse auxResponse;
            HttpResponseMessage httpResponse = new HttpResponseMessage();
            string responseJson = "";
            try
            {
                httpResponse = await client.PostAsync(client.BaseAddress, byteContent); // Error while sending request

                responseJson = await httpResponse.Content.ReadAsStringAsync();

                httpResponse.EnsureSuccessStatusCode();

                auxResponse = JSONSerializer<ApiResponse>.DeSerialize(responseJson);

                ApiResponse response = new ApiResponse()
                {
                        MessageId = !string.IsNullOrEmpty(auxResponse.Metadata.MessageId) ? auxResponse.Metadata.MessageId : "",
                        /* More info of the successful payment */
                }
            }
            catch (HttpRequestException)
            {
                try
                {
                    var errorResponse = JSONSerializer<ApiErrorResponse>.DeSerialize(responseJson);
                    
                    auxResponse = new ApiResponse()
                    {
                        Metadata = new VisionMetadata()
                        {
                            MessageType = !string.IsNullOrEmpty(errorResponse.Metadata.MessageType) ? errorResponse.Metadata.MessageType : "",
                            /* More info of the failed payment */
                    };
                    return auxResponse;
                }
                catch (Exception)
                {
                    return null;
                }
            }
            catch (Exception)
            {
                return null;
            }

This is the method used to convert from Json and to Json:

 public static class JSONSerializer<TType> where TType : class
    {
        /// <summary>
        /// Serializes an object to JSON
        /// </summary>
        public static string Serialize(TType instance)
        {
            var serializer = new DataContractJsonSerializer(typeof(TType));
            using (var stream = new MemoryStream())
            {
                serializer.WriteObject(stream, instance);
                return Encoding.Default.GetString(stream.ToArray());
            }
        }

        /// <summary>
        /// DeSerializes an object from JSON
        /// </summary>
        public static TType DeSerialize(string json)
        {
            using (var stream = new MemoryStream(Encoding.Default.GetBytes(json)))
            {
                var serializer = new DataContractJsonSerializer(typeof(TType));
                return serializer.ReadObject(stream) as TType;
            }
        }
    }

Also, all the classes involved are built like this:

 [DataContract (Namespace = "root")]
    public class ProductRequest
    {
        [DataMember(Name = "metadata")]
        public Metadata Metadata { get; set; }

        [DataMember(Name = "data")]
        public DataRequest Data { get; set; }
    }

I would like to figure out why the PostAsync method is failing in the server or why I am getting that error.

I noticed that the error was showing when consuming the PostAsync method because I had a logging function writting into a file for every line executed and it always stopped after the PostAsync method, it did not get to ** responseJson = await httpResponse.Content.ReadAsStringAsync();**

Also when debugging I found that the code was going straight to the Catch(Exception)

The API can be reached with Postman from the server, also if I execute the dll on the server from a client simulating app it also reaches the api.

I've made sure that the server has the framework installed

I´m not sure what else can be done in order to solve it

Edrumaz
  • 1
  • 1
  • Not related to your issue but [you are using the HttpClient wrong and it's destabilizing your software](https://www.aspnetmonsters.com/2016/08/2016-08-27-httpclientwrong/) – Wiktor Zychla Apr 11 '23 at 18:13
  • Is there a specific reason why you are using an ancient version of dotnet? – Fildor Apr 11 '23 at 19:27
  • `client.PostAsync(client.BaseAddress, byteContent);` <- that doesn't make any sense. The client already is set to the baseaddress, why feed it again? – Fildor Apr 11 '23 at 19:29
  • My guess would be similar, the code tries to post to wrong address. – Wiktor Zychla Apr 11 '23 at 20:17
  • @Fildor I am working on an existing proyect, and this was developed a few years ago, I am unable to use a newer version – Edrumaz Apr 13 '23 at 17:04
  • @WiktorZychla The URL from the API is set on de project properties and it does not change on the whole flow, i even tried printing the URL just before the postAsync method and it seemed ok. – Edrumaz Apr 13 '23 at 17:05
  • @Fildor I see, what you mean, i will fix that – Edrumaz Apr 13 '23 at 17:06
  • My advice would be to [setup a proxy, like Fiddler](https://stackoverflow.com/questions/22500299/how-can-i-trace-the-httpclient-request-using-fiddler-or-any-other-tool), and configure your httpclient to use it. In the proxy you'll see what goes out – Wiktor Zychla Apr 13 '23 at 18:38

0 Answers0