Web API: No MediaTypeFormatter is available to read an object of type 'IEnumerable`1' from content with media type 'text/plain'

23,967

Solution 1

I believe (because I don't have time to test it now) that you need to explicitly set the Status Code on the responseMessage you are passing to HttpResponseException. Normally, HttpResponseException will set the status code for you, but because you are providing a responsemessage explicitly, it will use the status code from that. By default, `HttpResponseMessage has a status code of 200.

So what is happening is you are getting an error on the server, but still returning a 200. Which is why your client is trying to deserialize the text/plain body produced by StringContent, as if it were an IEnumerable.

You need to set

responseMessage.StatusCode = HttpStatusCode.InternalServerError

in your exception handler on the server.

Solution 2

How about just using ReadAsStringAsync if your WebAPI is expecting to return content in plain text?

response.Content.ReadAsStringAsync().Result;
Share:
23,967
Water Cooler v2
Author by

Water Cooler v2

https://sathyaish.net/?c=pros https://www.youtube.com/user/Sathyaish

Updated on September 10, 2020

Comments

  • Water Cooler v2
    Water Cooler v2 over 3 years

    I get this error in my client (an ASP.NET MVC application) from a call to my ASP.NET Web API. I checked and the Web API is returning the data alright.

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

    I believe that I can inherit from DataContractSerializer and implement my own serializer which can attach the Content-Type HTTP header as text/xml.

    But my question is: is that necessary?

    Because if it was, it would mean that the default DataContractSerializer does not set this essential header. I was wondering if Microsoft could leave such an important thing out. Is there another way out?

    Here's the relevant client side code:

    public ActionResult Index()
            {
                HttpClient client = new HttpClient();
    
                var response = client.GetAsync("http://localhost:55333/api/bookreview/index").Result;
    
                if (response.IsSuccessStatusCode)
                {
                    IEnumerable<BookReview> reviews = response.Content.ReadAsAsync<IEnumerable<BookReview>>().Result;
                    return View(reviews);
                }
                else
                {
                    ModelState.AddModelError("", string.Format("Reason: {0}", response.ReasonPhrase));
                    return View();
                }
            }
    

    And here's the server side (Web API) code:

    public class BookReviewController : ApiController
        {
            [HttpGet]
            public IEnumerable<BookReview> Index()
            {
                try
                {
                    using (var context = new BookReviewEntities())
                    {
                        context.ContextOptions.ProxyCreationEnabled = false;
    
                        return context.BookReviews.Include("Book.Author");
                    }
                }
                catch (Exception ex)
                {
                    var responseMessage = new HttpResponseMessage
                    {
                        Content = new StringContent("Couldn't retrieve the list of book reviews."),
                        ReasonPhrase = ex.Message.Replace('\n', ' ')
                    };
    
                    throw new HttpResponseException(responseMessage);
                }
            }
        }
    
    • Justin Self
      Justin Self over 11 years
      Have you tried setting your content type for the http request you are making?
    • frictionlesspulley
      frictionlesspulley over 11 years
      Try switching the return type from IEnumerable to List
    • Mark Jones
      Mark Jones over 11 years
      It looks like it is - Have you seen stackoverflow.com/questions/10428177/…
    • Darrel Miller
      Darrel Miller over 11 years
      @justnS You don't set content-type for GET requests. Only when you are sending a body i.e. PUT, POST, PATCH.
  • Darrel Miller
    Darrel Miller over 11 years
    The OP is only expecting a string if the server fails. I don't think your line above would actually compile.