0

I have an existing and functioning API, which now have to be able to get data from another external API. How do i do that best?

I have tried with using HTTPClient, but i can't seem to get it to work. The error i get:

"No MediaTypeFormatter is available to read an object of type 'IList`1' from content with media type 'text/html'." -> I get this error on line 37. Can you spot it and/or tell me how I can do this differently, taking into account that all i want is the data (From the external API) and not to display it using a view, as this is an API?

Code below. I have also created a Pastebin: https://pastebin.com/MuKjEVys

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Net;

namespace API.Controllers
{
[ApiVersion("1.0")]
[Route("api/v{version:apiVersion}/[controller]")]
[ApiController]
public class ExternalApiController : Controller
{
    private string ExternalApiLink = "https://blablabla.com/api";
    private string ExternalApiLinkGet = "/module/1/";
    [HttpGet("getdata")]
    public ActionResult<ExternalApi> GetDataFromExternal()
    {

        using (var client = new HttpClient())
        {
            client.BaseAddress = new Uri(ExternalApiLink);

            var requestApi = client.GetAsync(ExternalApiLinkGet);
            client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "XXXX");
            requestApi.Wait();

            var resultFromApi = requestApi.Result;

            if (resultFromApi.IsSuccessStatusCode)
            {
                var readResponse = resultFromApi.Content.ReadAsAsync<IList<ExternalApi>>();
                readResponse.Wait();

                var data = readResponse.Result;

                return Json(data);
            }else
            {
                return NotFound();
            }
        }
    }
}

}

Anders
  • 105
  • 1
  • 9
  • It is saying your api is returning html. Not json or xml. So apparently it is not returning what you expect. That's why you can't read it as a list. Inspect the response content to figure out why. – Jesse de Wit Mar 25 '19 at 22:14
  • But that would indicate that it is the other external API, that are not sending the data as JSON or? – Anders Mar 26 '19 at 08:22
  • Yes, you might be getting an exception page, or perhaps your calling the wrong url. Search the internet to find out how to inspect the response content and status code. That should give you an indication why this is happening. – Jesse de Wit Mar 26 '19 at 08:42
  • If I try to print "resultFromApi" before the if statement, i get a JSON response.. Here i can see that it is the correct link, i am trying to get data from and that content-type is text/html... Might this be the error? Should i just request with a body saying application/json? – Anders Mar 26 '19 at 09:40
  • You could try sending an [Accept header](https://stackoverflow.com/a/10679340/3883866) with your request (line 3 in that answer). The server should not be returning json with a text/html content-type... – Jesse de Wit Mar 26 '19 at 09:48
  • I have tried adding "client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));" ... But the error still occurs – Anders Mar 26 '19 at 09:55
  • So what you're saying is the response content is actually json, but the content-type is text/html? In that case the first thing to do is call the party that hosts the service and have them fix it. But in the meantime, I'll try to cook an answer for you. – Jesse de Wit Mar 26 '19 at 09:58
  • That is how i understand it... But on the other hand.. I am able to get the data by using Postman – Anders Mar 26 '19 at 10:14

1 Answers1

0

Your response content seems to be json, while the content-type is text/html. If that is the case, the first thing to do would be to call the party that is exposing the service and have them fix it. In the meantime you could just read the content of the response as a string, and deserialize that string:

// Note that I made this method async.
public async Task<IActionResult> GetDataFromExternal()
{
    using (var client = new HttpClient())
    {
        client.BaseAddress = new Uri(ExternalApiLink);

        // note that I moved this line above the GetAsync method.
        client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "XXXX");

        // note that I'm disposing the response
        using (var response = await client.GetAsync(ExternalApiLinkGet))
        {
            if (response.IsSuccessStatusCode)
            {
                // Since the response content is json, but the content-type
                // is text/html, simply read the content as a string.
                string content = await response.ReadAsStringAsync();

                // You can return the actual received content like below,
                // or you may deserialize the content before returning to make
                // sure it is correct, using JsonConvert.DeserializeObject<List<ExternalApi>>()
                // var data = JsonConvert.DeserializeObject<List<ExternalApi>>(content);
                // return Json(data);
                return Content(content, "application/json");
            }
            else
            {
                return NotFound();
            }
        }
    }
}
Jesse de Wit
  • 3,867
  • 1
  • 20
  • 41