I have a class in my web project:
public class MyClass
{
public int? Param1 { get; set; }
public int? Param2 { get; set; }
}
which is a parameter in my controller method:
public ActionResult TheControllerMethod(MyClass myParam)
{
//etc.
}
If I call the method using POST, the model binding works automatically (I use angular on the js side, which likely doesn't matter):
$http({
method: "post",
url: controllerRoot + "TheControllerMethod",
data: {
myParam: myParam
}
}).success(function (data) {
callback(data);
}).error(function () {
alert("Error getting my stuff.");
});
If I use a GET, the parameter is always null in the controller.
$http({
method: "get",
url: controllerRoot + "TheControllerMethod",
params: {
myParam: myParam
}
}).success(function (data) {
callback(data);
}).error(function () {
alert("Error getting my stuff.");
});
Does complex model binding using the default model binder only work for POSTs, or is there something I can do to make this work with a GET?
The answer is Yes. The difference between GET and POST requests is that a POST body can have a content type so they can be interpreted correctly on the server side as XML, or Json, so on; for GET, all you have is just a querystring.
With ASP.NET MVC you can indeed bind your model on a GET request, as long as you have the same query string parameter names as of the property names of your Model class. Example from this answer:
public class ViewModel
{
public string Name { set;get;}
public string Loc{ set;get;}
}
You can do a Get request like this
MyAction?Name=jon&Loc=America
and MVC will automatically bind your model:
[HttpGet]
public ViewResult MyAction(ViewModel model)
{
// Do stuff
return View("ViewName", model);
}
Why are you calling the property "data" in the POST, and "params" in the GET? Both should be called "data".
$http({
method: "get",
url: controllerRoot + "TheControllerMethod",
data: {
myParam: myParam
}
}).success(function (data) {
callback(data);
}).error(function () {
alert("Error getting my stuff.");
});
Related
I am using .Net Core 2.1. This is the function that takes the value of the input boxName from the user and is supposed to pass it to the controller - Create function when the "save button" is clicked.
<script type="text/javascript">
function Submit() {
var boxName = $("#boxID").val();
alert(boxName);
UNTIL HERE EVERYTHING IS FINE - THE ALERT RETURNS THE CORRECT VALUE
$.ajax({
type: "POST",
contentType: "application/json",
url: '/Box/Create',
datatype: 'json',
data: JSON.stringify({ ID: "#Model.Id", BoxName: boxName }),
success: function (response) {
alert("Box created");
}
error: function (response) {
alert("error");
}
});
}
IN THE CONTROLLER
public ActionResult Create(int ID, string BoxName)
{
Box _Box = new Box();
_Box.Name= BoxName;
_db.Boxes.Add(_Box);
_db.SaveChanges();
return RedirectToAction("Index");
}
THE STRING BoxName RECEIVED AS A PARAMETER FROM THE AJAX IS NULL
I even tried
public ActionResult Create([Bind(Include = "ID,BoxName")] Box Box)
but it didn't work either. The error was
Include is not a valid named attribute argument
Any help is appreciated.
Remove the content Type and don't use stringify. So your ajax call becomes
$.ajax({
type: "POST",
url: '/Box/Create',
datatype: 'json',
data: { ID: "#Model.Id", BoxName: boxName },
success: function (response) {
alert("Box created");
}
Edit: This is partially wrong though you should do it for clarity. If there is only one action and the verb is not specified in your controller, the action is done anyway regardless if it's POST or GET.
You are using a POST verb in your ajax, by default all actions in the controller are GET. Add the [HttpPost] attribute above your controller action.
[HttpPost]
public ActionResult Create(int ID, string BoxName)
{
...
}
You should create a binding from the body of the request : ie:
class CreateBinding {
public string ID { get; set;}
public string BoxName { get; set; }
}
And in you controller:
[HttpPost]
Public ActionResult Create([FromBody] CreateBinding binding)
{
var id = binding.ID;
var name = binding.BoxName;
....
}
>
I .net core 2.2 This is the object Object:
[Serializable]
public class oob
{
public int i { get; set; }
public string j { get; set; }
}
this is the action in "Home" Controller named Gett that takes oob as input from ajax
[HttpGet]
public IActionResult Gett(oob ww)
{
return Ok(ww);
}
Ajax
{
$.ajax({
type: "Get",
url: "Home/gett",
data: { ww: JSON.stringify({i:55,j:"weqe"})},
dataType: "json",
contentType:"json",
success: function (f) {
console.log(f);
},
error: function (f) {
console.log(f);
}
});
});
When request is made ,at the Gett(oob ww) i get an object with value of i=0 and j=null
Ideally you should not pass object to a GET request, for posting object, you should use POST.
If you still want, you need to change your GET method like following using FromQuery.
[HttpGet]
public IActionResult Gett([FromQuery] oob ww)
{
return Ok(ww);
}
And change your AJAX call like following.
$.ajax({
type: "Get",
url: "Home/gett",
data: {i:55,j:"weqe"},
dataType: "json",
contentType:"json",
success: function (f) {
console.log(f);
},
error: function (f) {
console.log(f);
}
});
Note: To pass the object you don't need JSON.stringify if you are using FromQuery for your API
I am trying to post a javascript object, representative of a Model, back to a controller using an ajax post. However, the model is always showing as null.
The model in question is as follows
public class Product
{
[Key]
public int Id { get; set; }
[Required(ErrorMessage = "Name is required and must not be empty.")]
[StringLength(200, ErrorMessage = "Name should not exceed 200 characters.")]
public string Name { get; set; }
public DateTime Created { get; set; }
[Required(ErrorMessage = "Price is required and must not be empty.")]
[DataType(DataType.Currency)]
public decimal Price { get; set; }
}
With the ajax call looking like so
$('#btnSaveNewProduct').click(function (e) {
e.preventDefault();
var form = $('#frmNewProduct');
if (form.valid()) {
var data = { // to be replaced with form values
Name: 'Bob',
Price: 34
};
//ajax call to save product
$.ajax({
type: "POST",
url: "#Url.Action("AddProduct", "Admin")",
contentType: "application/json",
dataType: "json",
data: data,
success: function (response) {
alert('done');
},
error: function (response) {
alert(response);
}
});
}
});
The controller method looks like the following
[HttpPost]
public JsonResult AddProduct([FromBody] Product product)
{
bool success = false;
// save product
success = true;
return new JsonResult(success);
}
Any insight would be most appreciated.
To get your code to work as desired, make the following three modifications to your code.
From the Ajax call, remove this: dataType: "json"
From the Ajax call, remove this: data:data
In the Ajax call, add this: data:JSON.stringify(data)
IMPORTANT POINTS TO NOTE:
When you are using the [FromBody] attribute, the Content-Type value determines the formatter for the ASP.NET Core MVC Framework to use for parameter binding.
Since your Content-Type is application/json, a raw JSON string and not a JSON object, should be passed as data. Hence, apply JSON.stringify.
See this reference: Parameter Binding Using [FromBody] Attribute
I found below working:
$.ajax({
method: "POST",
data: { "Name": "bob", "Price": 10},
url: "#Url.Action("AddProduct", "Admin")",
success: function (data) {
//success login
},
error: function (data) {
alert('error' + data.status);
}
});
no need to mention dataType and contentType in ajax call. And your controller will like below:
[HttpPost]
public ActionResult AddProduct(Product product)
{
//You logic will be here
}
I'm using Ajax to make model and send it to the controller.
Here is Model:
public class PersonDto{
public Guid Id { get; set; }
public int PersonAge { get; set; }
public string PersonName { get; set; }
public DateTime? DateCreated { get; set; }
}
Here is Controller:
[Route("EditPerson")]
[HttpPost]
public async Task<IActionResult> EditPerson(PersonDto offer) {
//Save to Entity FW
}
Here is Ajax:
var data = {
Id: $('#personModal #personModalTitle').text(),
PersonAge: $('#personModal #personId').val(),
PersonName: $('#personModal #personName').val()
};
var dataJson = JSON.stringify(data);
console.log(dataJson);
$.ajax({
type: 'POST',
url: 'Persons/EditPerson',
data: dataJson,
contentType: "application/json",
success: function (result) {
},
error: function (error) {
Alert("Error Saving offer changes!");
}
});
Here is Console Log (Json), everything looks great:
{"Id":"96f2ae80-45cc-4a6c-abe0-230c2cbd3043","PersonAge":"5","PersonName":"John"}
When I Debug PersonsController I see that my model is never populated, is not null, just no data in it.
I tried Adding DateCreated to Model in Ajax function, I tried parsing Age to int.
I tried adding [FromBody] annotation to PersonDto in Action, then I getting NULL to my model.
I don't know where I can make error here.
For JSON encoded body , just add a [FromBody] :
[Route("EditPerson")]
[HttpPost]
public async Task<IActionResult> EditPerson([FromBody] PersonDto offer)
{
return new JsonResult(offer);
}
Update :
Another way to do that is use a [ApiController] to decorate the controller class .
If there's no [ApiController] , you should add a [FromBody] to enforce the Model Binder to read from body .
Whether a camelCased or pascalCased payload or not important . It makes no difference .
Camel Case :
POST https://localhost:44372/api/values/EditPerson HTTP/1.1
Content-Type : application/json
{"id":"96f2ae80-45cc-4a6c-abe0-230c2cbd3043","personAge":"5","personName":"John"}
Pascal Case :
POST https://localhost:44372/api/values/EditPerson HTTP/1.1
Content-Type : application/json
{"Id":"96f2ae80-45cc-4a6c-abe0-230c2cbd3043","PersonAge":"5","PersonName":"John"}
Can you try to get your data as a JObject:
[FromBody] JObject offer
[Route("EditPerson")]
[HttpPost]
public async Task<IActionResult> EditPerson([FromBody] JObject offer) {
string Id = (string)form.SelectToken("Id")
string PersonAge= (string)form.SelectToken("PersonAge")
string PersonName= (string)form.SelectToken("PersonName")
}
As I can see from your code you are not sending variable, the one you expect, "offer".
When doing AJAX call and sending data, data parameters should be named as those you are expecting.
You should send data in this format:
{
offer: { PersonAge: 10, PersonName: 'Senad' }
}
Your call should look like this
var data = {
Id: $('#personModal #personModalTitle').text(),
PersonAge: $('#personModal #personId').val(),
PersonName: $('#personModal #personName').val()
};
$.ajax({
type: 'POST',
url: 'Persons/EditPerson',
data: { offer: data }, //no need to serialize it
dataType: 'json',
success: function (result) {
},
error: function (error) {
Alert("Error Saving offer changes!");
}
});
I hope this is helpful.
I am having problems passing a javascript array to an MVC3 controller, not sure what I am doing wrong but this code does work with standard WCF service.
$(function () {
$("button").click(function () {
Poster();
});
});
function Poster() {
var data = [];
data.push(new WidgetProperty("test1", "value1"));
alert(data.length);
$.post("Home/Test", {test : data});
}
function WidgetProperty(name, value) {
this.Name = name;
this.Value = value;
}
and controller is
[HttpPost]
public ActionResult Test(WidgetProperty[] test)
{
return View("About");
}
public class WidgetProperty
{
public string Name { get; set; }
public string Value { get; set; }
}
Any ideas why the object that comes to the controller has null values for the properties? Checked with fiddler and it appears it passing the correct values.
Thanks!
You should use JSON.stringify() on your data before you post it, and since you know the data type is JSON, it is best to specify that the data being posted is JSON.
$.post("Home/Test", {test : JSON.stringify(data) }, "json");
Live DEMO
Edit:
I researched this a little more and it seems that you need to include contentType: "application/json" in order for this to work in mvc3:
$.ajax({
type: "POST",
url: "Home/Test",
data: JSON.stringify(data),
success: function(data){},
dataType: "json",
contentType: "application/json"
});