locked
Bug with Web API deserialization? RRS feed

  • Question

  • User-593456013 posted

    I tried to setup a Web API service and a client Web API client.  The service is simple and returns a concrete type:

    [HttpGet]
    public IEnumerable<MyDataClass> GetMyDataClasses()
    {
        return _repository.GetMyDataClasses();
    }

    That works great.  I can see the XML in the browser, and I can get JSON back in fiddler.  The problem comes when I try and consume the service and deserialize the data back into my concrete.  The Client has access to the same "MyDataClass" and passes it as the generic parameter into this method:

    public T GetDataFromService<T>()
    {
        using (var httpClient = new HttpClient())
        {
            T result = default(T);
            Task<HttpResponseMessage> responseTask = null;
    
            httpClient.GetAsync(_endpoint).ContinueWith((requestTask) =>
            {
                responseTask = requestTask;
                HttpResponseMessage response = requestTask.Result;
    
                response.EnsureSuccessStatusCode();
    
                response.Content.ReadAsAsync<T>().ContinueWith((readTask) =>
                {
                    result = readTask.Result;
                });
            });
    
            // HACK: My version of the await keyword
            while (responseTask == null || !responseTask.IsCompleted || result == null) { }
    
            return result;
        }
    }

    When the code hits "result = readTask.Result", it bombs saying:

    "The input stream contains too many delimiter characters which may be a sign that the incoming data may be malicious."

    I tried out the JSON library from Newtonsoft and it works like a charm, just need to substitute the inner async call with:

    response.Content.ReadAsStringAsync().ContinueWith((readTask) =>
    {
        result = JsonConvert.DeserializeObject<T>(readTask.Result);
    });

    This was my previous post which showed the complete code that works.

     http://forums.asp.net/p/1772530/4845207.aspx/1?p=True&t=634654962270492783

    Wednesday, February 22, 2012 8:38 AM

Answers

  • User-797310475 posted

    Is that a rudimentary protection mechanism against DDOS attacks?

    Yes, it is a very rudimentary protection mechanism. We added it late in the game as a workaround. We will be providing a better mechanism for the next release.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, February 22, 2012 3:41 PM

All replies

  • User1616639336 posted

    You have to add the namespace System.Net.Http and use the ReadAsOrDefaultAsync<T>() method to parse the response.

    response.Content.ReadAsOrDefaultAsync<T>().Result;
    Wednesday, February 22, 2012 9:24 AM
  • User-593456013 posted

    I get the same error whether I use "ReadAsAsync" or "ReadAsOrDefaultAsync".  Here is the complete code I'm using:

    public T GetDataFromService<T>()
    {
        using (var httpClient = new HttpClient())
        {
            var response = httpClient.GetAsync(_endpoint).Result;
    
            // This doesn't work:
            return response.Content.ReadAsAsync<T>().Result;
    
            // This doesn't work:
            return response.Content.ReadAsOrDefaultAsync<T>().Result;
    
            // This DOES work:
            return JsonConvert.DeserializeObject<T>(response.Content.ReadAsStringAsync().Result);
        }
    }

    Any ideas?

    Wednesday, February 22, 2012 9:35 AM
  • User1616639336 posted

    i think that is a limitation in the System.Net.Http.Formatting.dll. so go ahead with json.net. you can also replace the default json formatter with json.net if you like. https://github.com/ChristianWeyer/Thinktecture.Web.Http/blob/master/Thinktecture.Web.Http/Formatters/JsonNetFormatter.cs

    Wednesday, February 22, 2012 9:58 AM
  • User1594254982 posted

    You can modify the following static property on the MediaTypeFormatter class (default is 'false') to skip the error:

    public static bool SkipStreamLimitChecks { get; set; }

    BTW, this property is not visible in VS Intellisense, but you should still be able to use it. Please let us know otherwise.

    Wednesday, February 22, 2012 10:12 AM
  • User-593456013 posted

    Where is that property?  I don't see any statics on the MediaTypeFormatter class.  I can't find that property anywhere.

    Wednesday, February 22, 2012 10:24 AM
  • User1594254982 posted

    It's on the the MediaTypeFormatter class only. But this property is not visible in VS Intellisense, but you should still be able to use it. 

    Wednesday, February 22, 2012 10:26 AM
  • User-593456013 posted

    OK cool, I see it now. What exactly does that property do?  Is there a size limit on the stream?  Or some other kind of limitation?

    Wednesday, February 22, 2012 10:27 AM
  • User1616639336 posted

    the property enable or disable the delimeter counter during reading the stream. the current limit is 1000 delimeters.

    Wednesday, February 22, 2012 10:34 AM
  • User-593456013 posted

    Is that a rudimentary protection mechanism against DDOS attacks?

    Wednesday, February 22, 2012 10:55 AM
  • User-1509718999 posted

    This works for me when reading objects:

        var formatter = new JsonMediaTypeFormatter();

        var serializer = new DataContractJsonSerializer(type);

        formatter.SetSerializer(type, serializer);

        var formatters = new List<MediaTypeFormatter> { formatter };

        T data = response.Content.ReadAsOrDefaultAsync<T>(formatters).Result;

    When posting I find that I need to do the following so that the service gets the data properly:

        string mediaType = JsonMediaTypeFormatter.DefaultMediaType.MediaType;

        // Get formatters as above

        request.CreateContent<TData>(data, new MediaTypeHeaderValue(mediaType), formatters, new FormatterSelector());

        using (HttpResponseMessage response = m_client.SendAsync(request).Result)

    If anyone knows an easier way that would be good.

    Wednesday, February 22, 2012 11:28 AM
  • User-797310475 posted

    Is that a rudimentary protection mechanism against DDOS attacks?

    Yes, it is a very rudimentary protection mechanism. We added it late in the game as a workaround. We will be providing a better mechanism for the next release.

    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Wednesday, February 22, 2012 3:41 PM