Ajax Post web api model null - asp.net-web-api

I saw o lot of this questions here and i tried everything but still dont work, so this is my last try
this is my js:
var test = { backlog: "backlog", todo: "todo", done: "done"};
$.ajax({
type: 'POST',
data: JSON.stringify({ data: test }),
url: "Post",
contentType: 'application/json'
}).done(function (res) {
console.log('done' , res);
});
my controller: testt is null.
[HttpPost]
public test Post([FromBody] test testt)
{
test data = testt
return data;
}
my model:
public class test
{
public test(){}
public string backlog { get; set; }
public string todo { get; set; }
public string done { get; set; }
}
the problem is i send the data to the server but the json dont bind with the model
if i use this :
[HttpPost]
public test Post([FromBody] JObject testt)
{
test data = testt["data"].ToObject<test>();
return data;
}
will work but i dont want to do this i want the automatic bind cuz will be much much easier with complex data.
i'm sorry for duplicate but i dont know what to do anymore.

Related

Failed to post complex object in asp.net core api using jquery ajax

Failed to post complex object with list to asp.net core api using jquery ajax
Here is the Models
public class Bus
{
public int BusId { get; set; }
public string RegistrationNo { get; set; }
public IEnumerable<BusSeat> BusSeats { get; set; }
}
public class BusSeat : CoreModel
{
public int DecNumber { get; set; }
public int SeatId { get; set; }
}
Here is the Controller
[HttpPost]
public IActionResult Save([FromForm] Bus bus)
{
return Ok(bus);
}
Here is the javascript
var d = {
BusId: 1,
RegistrationNo: 'REG123',
BusSeats: [
{
DecNumber: 1,
SeatId:2,
},
{
DecNumber: 1,
SeatId: 4,
}
]
}
$.ajax({
type: 'post',
url: 'http://localhost:46060/api/bus/save',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: JSON.stringify({ bus: d }),
success: function (data) {
},
error: function (data) {
}
});
Request is successful, but i couldn't get any data. Anything i am missing?
You don't need stringify, contentType on ajax call, and don't need [FromForm] on the mvc action.
Just pass the complex object directly on the data parameter.
$.ajax({
type: 'post',
url: 'http://localhost:46060/api/bus/save',
dataType: 'json',
data: d,
success: function (response) {
},
error: function (response) {
}
});
As long as the complex json object matches the view models you define, the binding should 'magically' work.
[HttpPost]
public IActionResult Save(Bus bus)
{
return Ok(bus);
}
This is off topic but you should think about how you construct your uris since you're building web api. You don't want to still use good old RPC style on your uri.
Think about the controller name as resource collection, and use HttpMethod as verb.
So I would create BusesController instead of BusController (Or use [RoutePrefix("api/buses")]), because I think about the resource as a collection - buses.
[Route("api/[controller]")]
public class BusesController : Controller
{
// GET api/buses
[HttpGet]
public IActionResult()
{
// Return all buses
return OK(...);
}
// GET api/buses/1
[HttpGet]
public IActionResult(int id)
{
// Return individual bus
return OK(...);
}
// POST api/buses
[HttpPost]
public IActionResult Post(CreateBusViewModel model)
{
// Create a new bus and return newly created uri of the bus
return Created(...);
}
}
You can read more about Richardson Maturity Model here!
Change the From part in the action to [FromBody] and in the ajax call for data just say
data: JSON.stringify(d)
Rather than
data: JSON.stringify({ bus: d })

pass complex data to get call if api

I am trying to pass a viewmodel data to get call in web api..
here is the viewmodel properties
public class FilterViewModel
{
public int RegionID { get; set; }
public int StateID { get; set; }
public int DistrictID { get; set; }
public int UniversityID { get; set; }
public int CollegeID { get; set; }
public DateTime FromDate { get; set; }
public DateTime ToDate { get; set; }
}
here is the ajaxcall that i am trying to ..
to convert formdata to json object
function toSimpleJson() {
});
return json;
}
the ajax call
function GetFilteredRecords() {
var filterOptions = toSimpleJson();
$.ajax({
url: '/api/workassign',
data: JSON.stringify(filterOptions),
cache: false,
type: 'GET',
dataType: 'JSON',
success: function (data) {
debugger
}
});
}
here is the filteroptions data
here is the api controller get action
public IEnumerable<WorkAssignViewModel> Get([FromUri]FilterViewModel date)
{
}
here i am getting the form data into json object and the passing to controller by using json.stringify() which is suggested and in controller using [FROMUri] but still values are null......
please suggest me a solution to overcome
thank you..
You need to remove the JSON.stringify() andcontentTypefrom the ajax call. You making a GET and a GET does not have a body (thereforecontentType` option is pointless). You code ajax call should be
$.ajax({
url: '/api/workassign',
data: filterOptions,
cache: false,
type: 'GET',
dataType: 'JSON',
success: function (data) {
debugger
}
});
Note that is you have generated you form controls correctly based on the view having #model FilterViewModel and using the HtmlHelper methods to generate the form controls (#Html.TextBoxFor(m => m.RegionID) etc), then you can simply use data: #('form').serialize(),

post json string to mvc action via ajax comes null

I am posting a json object via ajax
$('#btnOrder').click(function (e) {
var jsonData =
{
ScheduleDate: '20/07/2015 17:00',
UnitNumber: '425196',
Length: 0.00
}
var url = "http://mywebsite.com/Home/MakeOrder";
$.ajax({
type: "POST",
dataType: "json",
url: url,
data: JSON.stringify(jsonData),
contentType: "application/json",
success: function(result) {
}
});
});
to the following action:
[HttpPost]
public PartialViewResult MakeOrder(string jsonData)
{
// some actions
return this.PartialView("_Summary", summaryModel);
}
Model:
public class OrderItem
{
public DateTime? ScheduleDate {get;set;}
public string UnitNumber {get;set;}
public float Length {get;set;}
}
The jsonData parameter value always comes null.
When I turn it into get ajax call via
var url = "http://mywebsite.com/Home/MakeOrder/?jsonData=" + jsonData
then the parameter comes fine as json string.
I need to send it via post.
EDIT ***** JS values
I'm debugging in Chrome and jsonData passed to 'ajax data:' is
JSON.stringify(jsonData)
gives
jsonData={"ScheduleDateTime":"20/07/2015 17:00","UnitNumber":"425196","Length":0.00}
if passed non stringified is:
jsonData = Object {"ScheduleDateTime":"20/07/2015 17:00","UnitNumber":"425196","Length":0.00}
Similar SO question that will solve your issue
You will need to probably create an model to accept a list of instead of a list of strings.
public class MyJSONObject{
public DateTime ScheduleDate { get; set; }
public string UnitNumber { get; set; }
public double Length { get; set; }
}
And accept it in your controller like:
[HttpPost]
public PartialViewResult MakeOrder(List<MyJSONObject> jsonData)
{
// some actions
return PartialView("_Summary", summaryModel);
}
And if it's not a list you need then just send off the single object and accept it in your controller as MyJSONObject jsonData instead.

json ajax complex type pass to MVC2 action

I know this has been asked before in a similar form, but I have hit a bit of problem here....
I have this classic problem of trying to pass a json complex type to MVC2.
The problem (refer to the code below): I can pass the value "subincidentID" to the controller but the values "CodeType", "MOCode" and "SubCode" are all NULL.
I HAVE installed the MVC2 future and registered "Microsoft.Web.MVC" in global.asax.cs and declare the JsonValueProviderFactory.
The JQuery bit:
$('#btnDone').click(function() {
var entity = {};
var dbCode = new Array();
dbCode[0] = { CodeType: "1", MoCode: "13", SubCode: "12" };
entity = { subincidentID: "1", codeData: dbCode };
$.ajax({
type: 'POST',
data: entity,
dataType: 'json',
async: false,
url: "/controller/SaveMOData",
success: function(result) {
alert('success!');
}
}); //end of post
}); //end of btnDone click function
Controller in MVC:
[HttpPost]
public JsonResult SaveMOData(MOSubMitModel mo)
{
if (ModelState.IsValid)
{
}
return Json(new { success = "true" });
}
Model class in MVC (2):
public class MOSubMitModel
{
public int subIncidentID { get; set; }
public List<dbCode> codeData { get; set; }
}
public class dbCode
{
public string CodeType { get; set; }
public string subCode { get; set; }
public string MoCode { get; set; }
}
Have I missed something here?
Do I have to declare any namespace on the controller page?
I am sure it is a small problem but I have been scratching my head the whole day about it....:-(..
Thanks in advance.
W. Lam
I've heard of issues using the following syntax
$.ajax({
type: "POST",
data: {prop:"Value"},
....
}
Instead you need to stringify the object
$.ajax({
type: "POST",
data: JSON.stringify({prop:"Value"}),
....
}
After some more trial-and-error and readings I have finally figured it out myself (Refer to the previous posting for details of the other components):
$('#btnDone').click(function() {
:
:
$.ajax({
type: 'POST',
data: JSON.stringify(entity),
contentType: 'application/json',
async: false,
url: "/controller/SaveMOData",
success: function(result) {
alert('success!');
}
}); //end of post
}); //end of btnDone click function
The problem was me NOT to include "contentType" (I had tried to inclide json stringify before but it ALL returns NULL if I do not include contentType)...so...to summarise the requirements under MVC2:
Download MVC Future .....Unzip the MVC future zip file and copy Microsoft.web.mvc to your project, and reference it In your project's global.asax.cs file, include the "Microsoft.web.mvc" namespace, and then include the following line at the end of the function "Application_start"
ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
Make the necessary changes in your jQuery as indicated above. It should be working (well it works for me!!)..Hope it helps anyone with the same problem.

Proper way to use AJAX Post in jquery to pass model from strongly typed MVC3 view

I'm a novice web programmer so please forgive me if some of my "jargon" is not correct.
I've got a project using ASP.NET using the MVC3 framework.
I am working on an admin view where the admin will modify a list of equipment. One of the functions is an "update" button that I want to use jquery to dynamically edit the entry on the webpage after sending a post to the MVC controller.
I presume this approach is "safe" in a single admin setting where there is minimal concern of the webpage getting out of sync with the database.
I've created a view that is strongly typed and was hoping to pass the model data to the MVC control using an AJAX post.
In the following post, I found something that is similar to what I am looking at doing:
JQuery Ajax and ASP.NET MVC3 causing null parameters
I will use the code sample from the above post.
Model:
public class AddressInfo
{
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
}
Controller:
public class HomeController : Controller
{
public ActionResult Index()
{
return View();
}
[HttpPost]
public ActionResult Check(AddressInfo addressInfo)
{
return Json(new { success = true });
}
}
script in View:
<script type="text/javascript">
var ai = {
Address1: "423 Judy Road",
Address2: "1001",
City: "New York",
State: "NY",
ZipCode: "10301",
Country: "USA"
};
$.ajax({
url: '/home/check',
type: 'POST',
data: JSON.stringify(ai),
contentType: 'application/json; charset=utf-8',
success: function (data.success) {
alert(data);
},
error: function () {
alert("error");
}
});
</script>
I have not had a chance to use the above yet. But I was wondering if this was the "best" method to pass the model data back to the MVC control using AJAX?
Should I be concerned about exposing the model information?
I found 3 ways to implement this:
C# class:
public class AddressInfo {
public string Address1 { get; set; }
public string Address2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string ZipCode { get; set; }
public string Country { get; set; }
}
Action:
[HttpPost]
public ActionResult Check(AddressInfo addressInfo)
{
return Json(new { success = true });
}
JavaScript you can do it three ways:
1) Query String:
$.ajax({
url: '/en/Home/Check',
data: $('#form').serialize(),
type: 'POST',
});
Data here is a string.
"Address1=blah&Address2=blah&City=blah&State=blah&ZipCode=blah&Country=blah"
2) Object Array:
$.ajax({
url: '/en/Home/Check',
data: $('#form').serializeArray(),
type: 'POST',
});
Data here is an array of key/value pairs :
=[{name: 'Address1', value: 'blah'}, {name: 'Address2', value: 'blah'}, {name: 'City', value: 'blah'}, {name: 'State', value: 'blah'}, {name: 'ZipCode', value: 'blah'}, {name: 'Country', value: 'blah'}]
3) JSON:
$.ajax({
url: '/en/Home/Check',
data: JSON.stringify({ addressInfo:{//missing brackets
Address1: $('#address1').val(),
Address2: $('#address2').val(),
City: $('#City').val(),
State: $('#State').val(),
ZipCode: $('#ZipCode').val()}}),
type: 'POST',
contentType: 'application/json; charset=utf-8'
});
Data here is a serialized JSON string. Note that the name has to match the parameter name in the server!!
='{"addressInfo":{"Address1":"blah","Address2":"blah","City":"blah","State":"blah", "ZipCode", "blah", "Country", "blah"}}'
You can skip the var declaration and the stringify. Otherwise, that will work just fine.
$.ajax({
url: '/home/check',
type: 'POST',
data: {
Address1: "423 Judy Road",
Address2: "1001",
City: "New York",
State: "NY",
ZipCode: "10301",
Country: "USA"
},
contentType: 'application/json; charset=utf-8',
success: function (data) {
alert(data.success);
},
error: function () {
alert("error");
}
});
This is the way it worked for me:
$.post("/Controller/Action", $("#form").serialize(), function(json) {
// handle response
}, "json");
[HttpPost]
public ActionResult TV(MyModel id)
{
return Json(new { success = true });
}
what you have is fine - however to save some typing, you can simply use for your data
data: $('#formId').serialize()
see http://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/ for details, the syntax is pretty basic.
If using MVC 5 read this solution!
I know the question specifically called for MVC 3, but I stumbled upon this page with MVC 5 and wanted to post a solution for anyone else in my situation. I tried the above solutions, but they did not work for me, the Action Filter was never reached and I couldn't figure out why. I am using version 5 in my project and ended up with the following action filter:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Filters;
namespace SydHeller.Filters
{
public class ValidateJSONAntiForgeryHeader : FilterAttribute, IAuthorizationFilter
{
public void OnAuthorization(AuthorizationContext filterContext)
{
string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME);
if (clientToken == null)
{
throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME));
}
string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value;
if (serverToken == null)
{
throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME));
}
System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken);
}
private const string KEY_NAME = "__RequestVerificationToken";
}
}
-- Make note of the using System.Web.Mvc and using System.Web.Mvc.Filters, not the http libraries (I think that is one of the things that changed with MVC v5. --
Then just apply the filter [ValidateJSONAntiForgeryHeader] to your action (or controller) and it should get called correctly.
In my layout page right above </body> I have #AntiForgery.GetHtml();
Finally, in my Razor page, I do the ajax call as follows:
var formForgeryToken = $('input[name="__RequestVerificationToken"]').val();
$.ajax({
type: "POST",
url: serviceURL,
contentType: "application/json; charset=utf-8",
dataType: "json",
data: requestData,
headers: {
"__RequestVerificationToken": formForgeryToken
},
success: crimeDataSuccessFunc,
error: crimeDataErrorFunc
});

Resources