// /api/BestPracticeSample ...standard POST public ComplexObject Post(ComplexObject dto) { // NOTE! There is a duplication conflict between these two Api signatures: since both are nullable, they can service the same request // public ComplexObject Post([FromBody] string value) // public ComplexObject Post([FromBody]ComplexObject dto) var result = new ComplexObject(); result.Name = dto.Name; result.Count = dto.Count; result.IsActive = dto.IsActive; ComplexObject.All.Add(result); return result; //this javascript // // var complexObject = { //< -- create new object // Name: 'Fred', // Count: 1122, // IsActive: false, // Children: [{ Name: 'Freddy Jr', Count: 1, IsActive: true, Children: null }] // } // // $.ajax({ // type: 'POST' // For POST or PUT, use JSON instead of the default Url-Encoded body // , url: '/api/BestPracticeSample' // , data: JSON.stringify(complexObject) // <-- 1 of 2 ...force JSON format // , contentType: 'application/json;charset=utf-8' // <-- 2 of 2 ...force JSON header // }) // .done(function (returnData) { // $('#BestPracticeSampleResult4').html(JSON.stringify(returnData)); // }) // .fail(function (xhr, result, status) { // alert(JSON.stringify(xhr)); // }); // // //produced this call, which hit this controller // // POST http://localhost:49278/api/BestPracticeSample HTTP/1.1 // Host: localhost:49278 // Connection: keep-alive // Content-Length: 121 // Accept: */* // Origin: http://localhost:49278 // X-Requested-With: XMLHttpRequest // User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 // Content-Type: application/json;charset=UTF-8 // Referer: http://localhost:49278/ApiSample // Accept-Encoding: gzip, deflate // Accept-Language: en-US,en;q=0.8 // //body--> {"Name":"Fred","Count":1122,"IsActive":false,"Children":[{"Name":"Freddy Jr","Count":1,"IsActive":true,"Children":null}]} //(JSON is best practice) // // }
// /api/BestPracticeSample ...standard PUT public ComplexObject Put(string id, ComplexObject dto) { var result = ComplexObject.All.FirstOrDefault(o => o.Name == id); result.Name = dto.Name; result.Count = dto.Count; result.IsActive = dto.IsActive; return result; //this javascript // // var complexObject = { // Name: 'Bob', // Count: 55155, //< -- updated value // IsActive: true, // Children: [ // { 'Name': 'Mary', 'Count': 4545, 'IsActive': true, 'Children': null }, // { 'Name': 'Larry', 'Count': 327, 'IsActive': false, 'Children': null }] // } // // // for PUT, the URL needs to identify the item to update, and then pass the new item via the body // var identifier = 'Bob' // var myUrl = '/api/BestPracticeSample?id=' + identifier; // expected to create: /api/BestPracticeSample?id=Bob // WCN Specific fix for Netscaler Url rewrite issue 'BuildRelativeUrl' // // $.ajax({ // type: 'PUT' // WEB API CAN ACCEPT primitive Types via the URL even for POSTs // // For POST or PUT, use JSON instead of the default Url-Encoded body // , url: myUrl // constructed above // , data: JSON.stringify(complexObject) // <-- 1 of 2 ...force JSON format // , contentType: 'application/json;charset=utf-8' // <-- 2 of 2 ...force JSON header // }) // .done(function (returnData) { // $('#BestPracticeSampleResult5').html(JSON.stringify(returnData)); // }) // .fail(function (xhr, result, status) { // alert(JSON.stringify(xhr)); // }); // // // //produced this call, which hit this controller // // PUT http://localhost:49278/api/BestPracticeSample?id=Bob HTTP/1.1 // Host: localhost:49278 // Connection: keep-alive // Content-Length: 180 // Accept: */* // Origin: http://localhost:49278 // X-Requested-With: XMLHttpRequest // User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 // Content-Type: application/json;charset=UTF-8 // Referer: http://localhost:49278/ApiSample // Accept-Encoding: gzip, deflate, sdch // Accept-Language: en-US,en;q=0.8 // //body--> {"Name":"Bob","Count":55155,"IsActive":true,"Children":[{"Name":"Mary","Count":4545,"IsActive":true,"Children":null},{"Name":"Larry","Count":327,"IsActive":false,"Children":null}]} //(JSON is best practice) // // }
public ComplexObject PostFromUrl(string name, int count, bool isActive) { var result = new ComplexObject(); result.Name = name; result.Count = count; result.IsActive = isActive; ComplexObject.All.Add(result); return result; //this javascript // // var complexObject = { // Name: 'Mike' , // Count: 989 , // IsActive: false , // // !!!!!!!!!!!! ALERT !!!!!!!!!!!!!!!!!! // // !!!!!!!!!!!! ALERT !!!!!!!!!!!!!!!!!! // // !! posting as a Url-Encoded body BREAKS when there are child collections !! // // will be null --> Children: [ // // will be null --> { 'Name': 'Mary', 'Count': 4545, 'IsActive': true, 'Children': null }, // // will be null --> { 'Name': 'Larry', 'Count': 327, 'IsActive': false, 'Children': null }] // } // // // $.ajax({ // type: 'POST' // WEB API CAN ACCEPT primitive Types via the URL even for POSTs // , url: '/api/AlternateSample?' + $.param(complexObject) // NOT RECOMMENDED, but possible... Add the object to the URL, instead of the body// only do this when needing to support links or bookmarks that will POST // //, data: theData // DO NOT PASS DATA HERE (body) // }) // .done(function (returnData) { // $('#AlternateSampleResult4').html(JSON.stringify(returnData)); // }) // .fail(function (xhr, result, status) { // alert(JSON.stringify(xhr)); // }); // // //produced this call, which hit this controller // // POST http://localhost:49278/api/AlternateSample?Name=Mike&Count=989&IsActive=false HTTP/1.1 // Host: localhost:49278 // Connection: keep-alive // Content-Length: 0 // Accept: */* // Origin: http://localhost:49278 // X-Requested-With: XMLHttpRequest // User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 // Referer: http://localhost:49278/ApiSample // Accept-Encoding: gzip, deflate // Accept-Language: en-US,en;q=0.8 // // //(no body) // }
// [FromBody] is needed because of using single primitive type, compared to URI as in PostFromUrl(string name, int count, bool isActive) // POST /api/AlternateSample ...using single string !!!!!! THIS CAN BE AN ODD ONE !!!!!!! on the javascript side public ComplexObject Post([FromBody] string username) { // NOTE! uses [FromBody] to specify that the string is in the body and not the URL var result = new ComplexObject(); result.Name = username != null ? username : "******"; ComplexObject.All.Add(result); return result; //BEST WAY... this javascript // // var theData = 'Jim'; // use simple javascript string, and pass as JSON // // $.ajax({ // type: 'POST' // For POST or PUT, use JSON instead of the default Url-Encoded body // , url: '/api/AlternateSample' // , data: JSON.stringify(theData) // <-- 1 of 2 ...force JSON format // , contentType: 'application/json;charset=utf-8' // <-- 2 of 2 ...force JSON header // }) // .done(function (returnData) { // $('#AlternateSampleResult3').html(JSON.stringify(returnData)); // }) // .fail(function (xhr, result, status) { // alert(JSON.stringify(xhr)); // }); // // //produced this call, which hit this controller // // POST http://localhost:49278/api/AlternateSample HTTP/1.1 // Host: localhost:49278 // Connection: keep-alive // Content-Length: 5 // Accept: */* // Origin: http://localhost:49278 // X-Requested-With: XMLHttpRequest // User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 // Content-Type: application/json;charset=UTF-8 // Referer: http://localhost:49278/ApiSample // Accept-Encoding: gzip, deflate // Accept-Language: en-US,en;q=0.8 // //body--> "Jim" //(JSON is best practice) // // // // // //ANOTHER WAY (worse)... this javascript // // // send oddly formatted object to resolve to Microsoft's handling of single primitive strings in the Url-Encoded body // var theData = { // // NOTE order of params must match WebApi... public bool GetIsUsernameAndEmailAvailable(string PrimaryEmail) // // NOTE sending single primitive types (not complex object), the JSON object should have empty leading identifier... // //This will work { '' : ''myString'' } results in body of ' =myString ' ...Binds to Post([FromBody]string stringName) // //This WONT work { stringName : 'myString' } results in body of ' stringName=myString ' ...This will NOT bind in ASP.netWebAPI because of how it decifer between Model binding and Formatters binding // '': 'Joe' //single string // } // // $.ajax({ // type: 'POST' // NOT PREFERRED... This will Pass via the body as URL encoded string // , url: '/api/AlternateSample' // , data: theData //pass the JS object // }) // .done(function (returnData) { // $('#AlternateSampleResult3').html(JSON.stringify(returnData)); // }) // .fail(function (xhr, result, status) { // alert(JSON.stringify(xhr)); // }); // //produced this call, which hit this controller // // POST http://localhost:49278/api/AlternateSample HTTP/1.1 // Host: localhost:49278 // Connection: keep-alive // Content-Length: 4 // Accept: */* // Origin: http://localhost:49278 // X-Requested-With: XMLHttpRequest // User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 // Content-Type: application/x-www-form-urlencoded; charset=UTF-8 // Referer: http://localhost:49278/ApiSample // Accept-Encoding: gzip, deflate // Accept-Language: en-US,en;q=0.8 // //body--> =Joe //(Url-Encoded, which is worse) // // }
// POST /api/FormSample ...using a html FORM as the contents of the POST, using complex type public ComplexObject Post(ComplexObject dto) { var result = new ComplexObject(); result.Name = dto.Name; result.Count = dto.Count; result.IsActive = dto.IsActive; ComplexObject.All.Add(result); return result; //in html ...NOTE form items must have a NAME assigned that matches the comples object property names // <form id="sampleForm"> // <input type="text" name="Name" value="Tom"/> // <input type="text" name="Count" value="3000" /> // <input type="hidden" name="IsActive" value="true"/> // <input type="checkbox" name="ignored" checked="checked" /> <!-- does not result to 'true' in Web Api when checked --> // </form> // // //this javascript // // var form = $('#sampleForm').serialize(); // // // NOTE !!!!! passing child collections may not be supported.... Url-Encoded body does not serialize at the API level if child collections are present // // $.ajax({ // type: 'POST' // Pass via the body as URL encoded string // , url: '/api/FormSample' // , data: form // Note! expects [FromBody] in Api controller when using form // //this is default... , contentType: 'application/x-www-form-urlencoded; charset=UTF-8' // }) // .done(function (returnData) { // $('#FormSampleResult1').html(JSON.stringify(returnData)); // }) // .fail(function (xhr, result, status) { // alert(JSON.stringify(xhr)); // }); // //produced this call, which hit this controller // // POST http://localhost:49278/api/FormSample HTTP/1.1 // Host: localhost:49278 // Connection: keep-alive // Content-Length: 44 // Accept: */* // Origin: http://localhost:49278 // X-Requested-With: XMLHttpRequest // User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 // Content-Type: application/x-www-form-urlencoded; charset=UTF-8 // Referer: http://localhost:49278/ApiSample // Accept-Encoding: gzip, deflate // Accept-Language: en-US,en;q=0.8 // //body--> Name=Tom&Count=3000&IsActive=true&ignored=on //(Url-Encoded, which is worse) // }
// POST /api/DefaultUrlEncodedBodySample ...using default FORM URL ENCODED DATA instead of best practice use of JSON public ComplexObject Post(ComplexObject dto) { // NOTE! There is a duplication conflict between these two Api signatures: since both are nullable, they can service the same request // public ComplexObject Post([FromBody] string value) // public ComplexObject Post([FromBody]ComplexObject dto) var result = new ComplexObject(); result.Name = dto.Name; result.Count = dto.Count; result.IsActive = dto.IsActive; ComplexObject.All.Add(result); return result; //this javascript // // var complexObject = { // Name: 'Dan', // Count: 544, // IsActive: true, // // !!!!!!!!!!!! ALERT !!!!!!!!!!!!!!!!!! // // !!!!!!!!!!!! ALERT !!!!!!!!!!!!!!!!!! // // !! posting as a Url-Encoded body BREAKS when there are child collections !! // // will break --> Children: [ // // will break --> { 'Name': 'Mary', 'Count': 4545, 'IsActive': true, 'Children': null }, // // will break --> { 'Name': 'Larry', 'Count': 327, 'IsActive': false, 'Children': null }] // } // // $.ajax({ // type: 'POST' // Pass via the body as URL encoded string // , url: '/api/DefaultUrlEncodedBodySample' // , data: complexObject // }) // .done(function (returnData) { // $('#DefaultUrlEncodedBodySampleResult2').html(JSON.stringify(returnData)); // }) // .fail(function (xhr, result, status) { // alert(JSON.stringify(xhr)); // }); // // //produced this call, which hit this controller // // POST http://localhost:49278/api/DefaultUrlEncodedBodySample HTTP/1.1 // Host: localhost:49278 // Connection: keep-alive // Content-Length: 32 // Accept: */* // Origin: http://localhost:49278 // X-Requested-With: XMLHttpRequest // User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/42.0.2311.135 Safari/537.36 // Content-Type: application/x-www-form-urlencoded; charset=UTF-8 // Referer: http://localhost:49278/ApiSample // Accept-Encoding: gzip, deflate // Accept-Language: en-US,en;q=0.8 // //body--> Name=Dan&Count=544&IsActive=true //(Url-Encoded, which is worse) }
private static void PopulateSamples() { _all = new List<ComplexObject>(); ComplexObject sample = new ComplexObject(); sample.Name = "Bob"; sample.Count = 5; sample.IsActive = true; _all.Add(sample); ComplexObject child1 = new ComplexObject(); child1.Name = "Mary"; child1.Count = 4545; child1.IsActive = true; _all.Add(child1); ComplexObject child2 = new ComplexObject(); child2.Name = "Larry"; child2.Count = 327; child2.IsActive = false; _all.Add(child2); List<ComplexObject> children = new List<ComplexObject>(); children.Add(child1); children.Add(child2); sample.Children = children; }