Water Cooler v2
Water Cooler v2

Reputation: 33850

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

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);
            }
        }
    }

Upvotes: 2

Views: 24362

Answers (2)

Maggie Ying
Maggie Ying

Reputation: 10175

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

response.Content.ReadAsStringAsync().Result;

Upvotes: 1

Darrel Miller
Darrel Miller

Reputation: 142014

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.

Upvotes: 4

Related Questions