4

This is my 4th production level system using AngularJS and web API 2 C# backend. I am not coming to this with no experience BUT....I just cannot get the very simple conversion working. I normally use complex models between the Angular UI and Web API 2 backend without issue so very frustrated as this is so simple.

I am posting the JSON below:

{
"appSelection": [
  {
  "name": "Withdrawal Service",
  "selected": true
  }
],
"dateSelection": {
  "startDate": "2016-06-13T23:00:00.000Z",
  "endDate": "2016-07-27T07:52:03.510Z"
},
"eventTypes": [
  {
  "name": "Fail",
  "selected": true
  },
  {
  "name": "Success",
  "selected": true
  }
]
}

To a Web API controller: (edited for brevity)

        [HttpPost]
        [Route("search")]
        [ResponseType(typeof(ProcessLog[]))]
        public async Task<IHttpActionResult> getLogs(LogRequest request)
        {
            string requestBody = string.Empty;
            using (var stream = new MemoryStream())
            {
                var context = (HttpContextBase)Request.Properties["MS_HttpContext"];
                context.Request.InputStream.Seek(0, SeekOrigin.Begin);
                context.Request.InputStream.CopyTo(stream);
                requestBody = Encoding.UTF8.GetString(stream.ToArray());
            }

Which accepts this model:

public class LogRequest
        {
            public DateViewModel DateSelection { get; set; }
            public NameAndSelect[] appSelection { get; set; }
            public NameAndSelect[] eventTypes { get; set; }
        }

        public class NameAndSelect
        {
            public bool selected { get; set; }
            public string name { get; set; }
        }
        public class DateViewModel
        {
            public DateTime startDate { get; set; }
            public DateTime endDate { get; set; }
        }

The output from the requestBody is

{"appSelection":[{"name":"Withdrawal Service","selected":true}],"dateSelection":{"startDate":"2016-06-13T23:00:00.000Z","endDate":"2016-07-27T07:52:03.510Z"},"eventTypes":[{"name":"Fail","selected":true},{"name":"Success","selected":true}]}

Which shows that the JSON is being correctly POST'ed to the web API controller but the auto model binding is failing. The request object (web api receiving model) is

DateSelection : null
appselection : null
eventTypes : null

I just cannot see why and where. Been trying this for > 2 days! would really appreciate a fresh pair of eyes.

Thanks in advance

Update #1:

Changed model to the below with still failing auto binding

public class LogRequest
        {
            public DateViewModel DateSelection { get; set; }
            public List<NameAndSelect> appSelection { get; set; }
            public List<NameAndSelect> eventTypes { get; set; }
        }

Update #2:

I have tried simplifying the model to

public class LogRequestViewModel
    {
        public string testString { get; set; }
        public DateTime startDate { get; set; }
        public DateTime endDate { get; set; }
        public DateSelection dateselection { get; set; }
     }
public class DateSelection
     {
        public string startDate { get; set; }
        public string endDate { get; set; }
     }

and posting:

{"teststring":"plap","startdate":"2016-07-27T09:28:38.404Z","enddate":"2016-07-27T09:28:38.404Z","dateselection"
:{"startdate":"2016-07-27T09:28:38.404Z","enddate":"2016-07-27T09:28:38.404Z"}}

I receive:

dateselection:null
enddate:      {27/07/2016 10:28:38}
startdate:    {27/07/2016 10:28:38}
teststring:   "plap"

Which suggests it is able to convert the datetime without issue but deeper objects are causing problems

15
  • Try using generic list for List<NameAndSelect> Commented Jul 27, 2016 at 8:07
  • I just tried to reproduce the error, and everything worked perfectly. I created an ApiController with a model just like yours and then posted with PostMan. Commented Jul 27, 2016 at 8:18
  • I'm not suprised @smoksnes - I see no reason it should fail Commented Jul 27, 2016 at 8:21
  • I just tried with JQuery.ajax request and it works.. Edit: Oh, a bit slow.. Nvm.. Commented Jul 27, 2016 at 8:22
  • 1
    @MadEddie, is it a blank project? If not, try to remove everything that might mess up the model binding. Formatters in config, modelbinders etc. As this works in a blank project I would assume that you got something behind the curtains that disrupts the model binding. Try remove everything piece by piece. Commented Jul 27, 2016 at 8:34

2 Answers 2

3

Thanks to @Smoksnes I commented out all JSON formatters which are in the startup classes and classes in App_Start. Unfortunately this did not resolve the problem. When run-commenting all the commented out lines I found the below in my WebApiConfig.cs

var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
            jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            jsonFormatter.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Serialize;
            jsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None;
            jsonFormatter.SerializerSettings.MaxDepth = 1;

The bottom line! Doh. Commenting ALL JSON formatters hadn't fixed it but re-enabling them all APART from this line fixed it. I guess I needed the combination of some of the other formatters but not MaxDepth one.

Thanks All

Sign up to request clarification or add additional context in comments.

2 Comments

The real question is; why was it there in the first place? And what breaks now when you removed it... :)
@smoksnes It was an attempt to stop Entity Framework from returning JSON containing entities which are deeply related/linked (see mass recursion) within my model. I now add ProxyCreationEnabled everytime I init my entity model :(
0
    public class AppSelection
{
    public string name { get; set; }
    public bool selected { get; set; }
}

public class DateSelection
{
    public string startDate { get; set; }
    public string endDate { get; set; }
}

public class EventType
{
    public string name { get; set; }
    public bool selected { get; set; }
}

public class RootObject
{
    public List<AppSelection> appSelection { get; set; }
    public DateSelection dateSelection { get; set; }
    public List<EventType> eventTypes { get; set; }
}
change this model to your model and then try hope it will useful for you

5 Comments

Same empty model I'm afraid
strange, are ou able to store this json o not.
@MadEddie why you using memory stream , curious to know
It is because the HTTPOST content can only be read once and the inbuilt model binding of web API reads it before this method
show the full code it's difficult to identify the error

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.