locked
JQueryMvcFormUrlEncodedFormatter returns the model as null RRS feed

  • Question

  • User1927636528 posted

    I have WebAPI post method which accepts a Complex model as input

    Sample code:

    public string Post([FromBody]Student value)
            {
                string name = value.Name;
                
                return name;
            }

    Occasionally in the production environment model object value is coming as null. I am able to reproduce the same problem in staging environment when I make the API calls using multiple threads

    Sample Code:

    static void Main(string[] args)
            {
               
                Thread t = null;
                for (int i = 0; i < 1000; i++)
                {
                   t = new Thread(new ThreadStart(ApiTest));
                    t.Start();
                }
    
                Console.WriteLine("main end");
                //Console.WriteLine(t.Result);
                Console.ReadLine();
            }
    
    
     private static void ApiTest()
            {
                
                var wc = new WebClient();
    	var url = "http://localhost:58565/api/values";
                wc.Headers.Add("content-type: application/x-www-form-urlencoded");
                var model = "Name=test&Age=10";
                var result = wc.UploadString(url,"POST", model);
                Console.WriteLine(result);
            }

    To analyze further I have created custom formatter deriving from JQueryMvcFormUrlEncodedFormatter, replaced the formatter in the WebApiConfig. Observed that when the model is null FormDataCollection is coming as empty and the Type of the readStream is ReadOnlyStream, it seems working fine when the readStream type is MemoryStream.

    Why the two types of streams are passed for readStream and why the FormDataCollection and model object is coming as null?

    My Custom formatter class:

    public class JsonFormUrlEncodedFormatter : JQueryMvcFormUrlEncodedFormatter
        {
            public override bool CanReadType(Type type)
            {
                var res = base.CanReadType(type);
                return res;
            }
            public override bool CanWriteType(Type type)
            {
                var res = base.CanWriteType(type);
                return res;
            }
            public override Task<object> ReadFromStreamAsync(Type type, Stream readStream, HttpContent content, IFormatterLogger formatterLogger)
            {
                if (type == null)
                {
                    throw new ArgumentNullException("type");
                }
                if (readStream == null)
                {
                    throw new ArgumentNullException("readStream");
                }
                return base.ReadFromStreamAsync(typeof(FormDataCollection), readStream, content, formatterLogger).ContinueWith((obj) =>
                    {
                        FormDataCollection fd = (FormDataCollection)obj.Result;
                        try
                        {
                            var res = fd.ReadAs(type, String.Empty, RequiredMemberSelector, formatterLogger);
                            return res;
                        }
                        catch (Exception e)
                        {
                            if (formatterLogger == null)
                            {
                                throw;
                            }
                            formatterLogger.LogError(String.Empty, e);
                            return GetDefaultValueForType(type);
                        }
                    });
            }
        }

    Wednesday, April 8, 2015 10:17 AM

Answers