83

This is the situation:

Their is a external webservice in Servoy and I want to use this service in a ASP.NET MVC applicatie.

With this code I attempt to get the data from the service:

HttpResponseMessage resp = client.GetAsync("http://localhost:8080/servoy-service/iTechWebService/axws/shop/_authenticate/mp/112818142456/82cf1988197027955a679467c309274c4b").Result;
resp.EnsureSuccessStatusCode();

var foo = resp.Content.ReadAsAsync<string>().Result;

but when I run the application I get the next error:

No MediaTypeFormatter is available to read an object of type 'String' from content with media type 'text/plain'.

If I open Fiddler and run the same url, I see the right data but the content-type is text/plain. However I see in Fiddler also the JSON that I want...

Is it possible to solve this at client side or is it the Servoy webservice?

Update:
Used HttpWebRequest instead of HttpResponseMessage and read the response with StreamReader...

Community
  • 1
  • 1
Renzzs
  • 1,046
  • 2
  • 11
  • 20

3 Answers3

141

Try using ReadAsStringAsync() instead.

 var foo = resp.Content.ReadAsStringAsync().Result;

The reason why it ReadAsAsync<string>() doesn't work is because ReadAsAsync<> will try to use one of the default MediaTypeFormatter (i.e. JsonMediaTypeFormatter, XmlMediaTypeFormatter, ...) to read the content with content-type of text/plain. However, none of the default formatter can read the text/plain (they can only read application/json, application/xml, etc).

By using ReadAsStringAsync(), the content will be read as string regardless of the content-type.

Vahid Farahmandian
  • 6,081
  • 7
  • 42
  • 62
Maggie Ying
  • 10,095
  • 2
  • 33
  • 36
  • 2
    I am having this same problem, except the error message is `"No MediaTypeFormatter is available to read an object of type 'Int32' from content with media type 'text/html'." ` Is there a similar solution for int32? – Eric Furspan Oct 18 '16 at 13:57
  • 3
    Quanda: You can use return JsonConvert.DeserializeObject(resultString);, result String is the result after ReadAsStringAsync(), JsonConvert is from Newtonsoft.Json. You can download this library from NuGet. This is also very useful for Portable Libraries and not only applies to Int32, It applies to almost every type or class. – Jav_1 Nov 30 '16 at 03:14
6

Or you can just create your own MediaTypeFormatter. I use this for text/html. If you add text/plain to it, it'll work for you too:

public class TextMediaTypeFormatter : MediaTypeFormatter
{
    public TextMediaTypeFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));
    }

    public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
    {
        return ReadFromStreamAsync(type, readStream, content, formatterLogger, CancellationToken.None);
    }

    public override async Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger, CancellationToken cancellationToken)
    {
        using (var streamReader = new StreamReader(readStream))
        {
            return await streamReader.ReadToEndAsync();
        }
    }

    public override bool CanReadType(Type type)
    {
        return type == typeof(string);
    }

    public override bool CanWriteType(Type type)
    {
        return false;
    }
}

Finally you have to assign this to the HttpMethodContext.ResponseFormatter property.

t3chb0t
  • 16,340
  • 13
  • 78
  • 118
5

I know this is an older question, but I felt the answer from t3chb0t led me to the best path and felt like sharing. You don't even need to go so far as implementing all the formatter's methods. I did the following for the content-type "application/vnd.api+json" being returned by an API I was using:

public class VndApiJsonMediaTypeFormatter : JsonMediaTypeFormatter
{
    public VndApiJsonMediaTypeFormatter()
    {
        SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/vnd.api+json"));
    }
}

Which can be used simply like the following:

HttpClient httpClient = new HttpClient("http://api.someaddress.com/");
HttpResponseMessage response = await httpClient.GetAsync("person");

List<System.Net.Http.Formatting.MediaTypeFormatter> formatters = new List<System.Net.Http.Formatting.MediaTypeFormatter>();
formatters.Add(new System.Net.Http.Formatting.JsonMediaTypeFormatter());
formatters.Add(new VndApiJsonMediaTypeFormatter());

var responseObject = await response.Content.ReadAsAsync<Person>(formatters);

Super simple and works exactly as I expected.

Zamotic
  • 1,127
  • 8
  • 12
  • I get similar kind of issue for object of type 'FileStreamResult' from content with media type 'text/calendar'. How can I fix this? API is returning iCal (File stream) – user2837480 Jun 11 '21 at 07:57