I have an ajax call to a Controller on an ASP.NET MVC solution that looks like this:
$.ajax({
url: "ControllerClass/ControllerMethod?date=" + date,
type: "POST",
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (result) {
globalVariable = result; // This is for later...
DoSomething(result);
},
async: true,
processData: false
})
The controller once it has done all the work on the server side, it returns an Object which contains different property types (an Int, an Array of Int and a List of Objects)
The way that I return that data from the controller back to the JS file is...
return Json(new
{
summary = objectResult
});
The point is that from the JavaScript, now I would like to call a different Controller with the information that I have stored on my globalVariable which is defined in my JavaScript like this:
var globalVariable
That var located at the top of my JS file...
Well, the way I am trying to call back my controller with that variable looks like this:
$.ajax({
url: "ControllerClass/ControllerMethod?result=" + globalVariable,
type: "POST",
dataType: 'json',
contentType: 'application/json; charset=utf-8',
success: function (result) {
DoSomethingNewWithThisresult(result)
},
async: true,
processData: false
})
And this is my controller in C#.
public IActionResult ControllerMethod(JsonResult result)
{
DoSomethingHereWithTheResult(result);
}
Why if I put a breakpoing on my last controller, the result variable is empty? I checked on Chrome that the variable contains all the data that I am looking for. Actually, if I just pass one of the properties of the object, it goes to the controller just fine but I can't pass the whole Object...
Try to create your own custom Model instead of using JsonResult as parameter in the action and use it in ajax call this way:
$.ajax({
url: "ControllerClass/ControllerMethod",
type: "POST",
dataType: 'json',
data: { Summary: globalVariable.summary},
contentType: 'application/json; charset=utf-8',
success: function (result) {
DoSomethingNewWithThisresult(result)
}
})
public class YourClass
{
public string Summary { get; set;}//// string type or whatever it is
}
public IActionResult ControllerMethod(YourClass result)
{
DoSomethingHereWithTheResult(result);
}
alternatively you can also use JSON.stringify to serialize your object this way:
var customObject={
"Summary" : globalVariable.summary
};
$.ajax({
url: "ControllerClass/ControllerMethod",
type: "POST",
dataType: 'json',
data: JSON.stringify(customObject),
contentType: 'application/json; charset=utf-8',
success: function (result) {
DoSomethingNewWithThisresult(result)
}
})
Assuming this is a Web API controller, there are multiple ways to read a complex type from the URL - (there are also similar options to MVC controllers)
If the parameters are passed in the UrL, and assuming they map 1:1 to your object, you can decorate your object with the [FromUri] attribute, example:
public class GeoPoint
{
public double Latitude { get; set; }
public double Longitude { get; set; }
}
public ValuesController : ApiController
{
public HttpResponseMessage Get([FromUri] GeoPoint location) { ... }
}
Another option which gives you more flexibility controlling the creation of your object and populating the parameters is by using the IModelBinder interface and [ModelBinder] attribute.
You can implement the IModelBinder interface with the only method "BindModel" to access the HTTP request just right before your Controller method is called, create your object, read the URL query params, set the values in your object then finally assign it to the Model property of the bindingContext:
A simple example would be like this:
public bool BindModel(HttpActionContext actionContext, ModelBindingContext bindingContext)
{
if (bindingContext.ModelType == typeof(MyComplexType))
{
MyComplexType model ;
//You can use the value provider or get it from the HttpRequest
//var theValue = bindingContext.ValueProvider.GetValue ( bindingContext.ModelName);
//var theValue = request.RequestUri.ParseQueryString ( ) ;
if ( new MyComplexTypeConverter( ).TryParse ( actionContext.Request, out model) )
{
bindingContext.Model = model;
return true;
}
else
{
bindingContext.ModelState.AddModelError( bindingContext.ModelName, "Cannot convert request to MyComplexType");
return false;
}
}
return false ;
}
Here is a reference documentation: http://www.asp.net/web-api/overview/formats-and-model-binding/parameter-binding-in-aspnet-web-api
Related
I'm very new at dealing with javascript. I have a listbox filled with IEnumerable values that I want to pass back to the controller but I'm stuck on how I would go about doing so. Any suggestions?
Try this
ASP.Net MVC How to pass data from view to controller
or try use the Jquery ajax call this way. So I'm not sure what about lis tbox is.
Javascript
$(document).ready(function () {
var listbox = $('#yourListboxID');
var formData = new FormData();
formData.append('Value', listbox[0].value);
formData.append('ID', listbox[0].id);
formData.append('OtherVariable',"..." );
$.ajax({
url: 'Ajax/Test', //url--> controller/Method
type: "POST",
dataType: 'json', // data type return form your controller
data: formData,
cache: false,
contentType: false,
processData: false,
success: function (result) {
console.log(result); //<--- "Sucess"
},
error: function (xhr, resp, text) {
console.log(xhr, resp, text);
}
})
});
AjaxController.cs
[Route("[controller]/[action]")]
public class AjaxController : Controller
{
[HttpPost]
public JsonResult Test(string value01)
{
var ID = Request.Form["ID"].ToString();
var Value = Request.Form["Value"].ToString();
return Json("Sucess");
}
}
I have this list of objects which I need to send from my angularjs javascript code:
var dataToSend = [{
SubId: "c9cb1d3e-8c32-4a9e-8f0d-0008196776de",
CustomerName: "Blah"
}, {
SubId: "aaaa1d3e-8c32-4a9e-8f0d-0008196776de",
CustomerName: "Blah2"
}]
I've tried these different variations but none of them are working:
1.
$http.post("url",
{
dataType: 'json',
headers: {
contentType: "application/json; charset=utf-8",
},
method: "POST",
data: dataToSend,
}).then...
2.
$http.post("url",
{
data: $.param(dataToSend),
}).then...
3
$http.post("url",
{
data: angular.toJson(dataToSend),
}).then...
4
$http.post("url",
{
data: { customers: dataToSend },
}).then...
5
$http.post("url",
{
data: JSON.stringify({ customers: dataToSend }),
}).then...
My API side code is (I have tried with [FromBody] attribute but no luck there):
[HttpPost]
public async Task<JsonResult> CreateCustomers(List<Customer> customers)
{
// customers is always null
}
And this is my Customer.cs:
public partial class Customer
{
public System.Guid SubId { get; set; }
public string CustomerName { get; set; }
}
Can you please help me? I have tried posting to CreateCustomers(Customer c) without using a list and its working as expected. But when I use a list, its always coming as null on the other side.
EDIT:
$.ajax is working but $http.post isn't. Any idea why?
var request = $.ajax({
dataType: "json",
url: "url",
method: "POST",
data: { '': dataToSend }});
Are you sending JSON ( Include dataType: 'json')
$http({
url: "url",
dataType: 'json',
method: 'POST',
data: dataToSend,
headers: {
contentType: "application/json; charset=utf-8",
}
})
In C# add FromBody in parameter
[HttpPost]
public async Task<JsonResult> CreateCustomers([FromBody]]List<Customer> customers)
{
// customers is always null
}
More on Ajax parameters
contentType is the type of data you're sending, so application/json; charset=utf-8 is a common one, as is application/x-www-form-urlencoded; charset=UTF-8, which is the default.
dataType is what you're expecting back from the server: json, html, text, etc.
This should work. post full code if you face issue
use [ModelBinder] in front of your param.
[HttpPost]
public async Task<JsonResult> CreateCustomers([ModelBinder]List<Customer> customers)
{
// customers is always null
}
Web API only uses model binding for simple types, falling back on formatters for everything else. Adding [ModelBinder] forces the complex types to use model binding anyway.
Your post data is not matched with the parameter List<Customer>.
Change your server side method to something like:
[HttpPost]
public async Task<JsonResult> CreateCustomers(JObject queryParam)
{
// populate your list here
// for eaxample : var customers = queryParam["customers"].ToString();
}
And also you can use this code to send data to the server:
$http({
url: 'url',
dataType: 'json',
method: 'POST',
data: jsonData,
headers: { "Content-Type": "application/json" }
}).success(function(response){ $scope.response = response;
}).error(function(error){ $scope.error = error; });
I was quite confused with constructing data parameter of ajax using ASP.NET MVC and Webform and need an explanation from stackoverflow community.
First scenario (passing javascript object literal as data parameter in ajax using MVC) Results: It worked
MVC Controller
[HttpPost]
public JsonResult Register(string Name, string Birthday, int Gender)
{
.
.
.
return Json(message);
}
Javascript Code:
$.ajax({
url: "/Test/Register",
method: "POST",
dataType: "json",
data: {
Name:name,
Birthday:birthday,
Gender:gender
}
}).success(function (response) {
alert(response);
}).error(function (response) {
alert(response);
});
Second scenario (passing javascript object literal as a string as data parameter in ajax using MVC) Results: Cause error 500 (Internal Server Error)
Javascript Code:
var name = $('#Name').val();
var birthday = $('#Birthday').val();
var gender = $('#Gender').val();
var data = "{ Name:'" + name + "', Birthday:'" + birthday + "', Gender:'" + gender + "'}";
$.ajax({
url: "/Test/Register",
method: "POST",
dataType: "json",
data: data,
}).success(function (response) {
alert(response);
}).error(function (response) {
alert(response);
});
Results were different when I tested it on ASP.NET Webforms
Third scenario (passing javascript object literal as a string as data parameter in ajax using Webforms) Results: It worked
Webform WebMethod
[WebMethod]
public static string Submit(string Name, String Salary)
{
return "Success";
}
Javascript Code:
var name = $("#Name").val();
var salary = $("#Salary").val();
var data = "{ Name:'" + name + "', Salary:'" + salary + "'}";
$.ajax({
url: '/WebForm3.aspx/Submit',
contentType: "application/json; charset=utf-8",
method: 'POST',
data: data,
dataType: 'json',
success: function (response)
{
console.log(response);
},
error: function (response)
{
console.log(response);
}
});
Forth scenario (passing javascript object literal as data parameter in ajax using Webforms) Results: Cause error 500 (Internal Server Error)
$.ajax({
url: '/WebForm3.aspx/Submit',
contentType: "application/json; charset=utf-8",
method: 'POST',
data: {
Name: name,
Salary: salary
},
dataType: 'json',
success: function (response)
{
console.log(response);
},
error: function (response)
{
console.log(response);
}
});
Questions:
Why?
Will the scenarios that worked here on jQuery's ajax also work on other javascript frameworks like angularJS's $http service?
I also saw some scenarios on the internet that constructs its ajax data parameter using '=' example:
var reservation = { "CourseCode": courseCode.val().toString(), "Section": section.val().toString(), "DateFrom": dateF.toString(), "DateTo": dateT.toString(), "Schedule": reservations };
$.ajax({
url: '/ReserveSubject',
type: 'POST',
data: 'reservation=' + JSON.stringify(reservation),//Like this
Can anyone show more more ways to construct ajax data parameters aside from the scenarios above? It would also be much appreciated if someone could also show the most eloquent way of constructing data parameter.
No takers?
http://api.jquery.com/jquery.ajax/
documentation on jQuery's ajax data exerpts this:
data Type: PlainObject or String or Array Data to be sent to the
server. It is converted to a query string, if not already a string.
It's appended to the url for GET-requests. See processData option to
prevent this automatic processing. Object must be Key/Value pairs. If
value is an Array, jQuery serializes multiple values with same key
based on the value of the traditional setting (described below).
so you can pass it, string, aray or plain object,, while in Angulars data you can pass only string|object
https://docs.angularjs.org/api/ng/service/$http
so that's not same as in your examples,, you'll have to adjust if you send arrays
I suggest reducing the number of parameters on your controller actions to a single model object like:
public class RegisterModel
{
public string Name {get; set;}
public string Birthday {get; set;}
public int Gender {get; set;}
}
This is just good practice for clean code anyway.
And then in the client side you can have model builders which take the data you want to send and then send up this object instead of a bunch of parameters
I have the following AJAX call, simplified to try and pin point the problem:
$('#userUpdateForm').submit(function (e) {
$.ajax({
type: "POST",
url: '#Url.Action("submitForm", "Home")',
data: JSON.stringify({
'blue': window.glbBlue,
'eg2': 'eg3'
}),
contentType: "application/json; charset=utf-8",
success: function (result) {
alert("Success");
},
error: function (result) {
alert("A problem occured when submitting the form.");
}
});
e.preventDefault();
});
This calls into the following method:
[HttpPost]
public ActionResult submitForm(string json)
{
System.Diagnostics.Debug.WriteLine("made it here");
var check = System.Web.Helpers.Json.Decode(json);
System.Diagnostics.Debug.WriteLine(check);
System.Diagnostics.Debug.WriteLine(check.glbBlue);
return View();
}
However, the JSON the controller receives is null. Why does this happen? I can see in the browser that there is a request payload, with the values I'd expect. 'Window.glbBlue' is a global value, which I also know has been set properly as alerts were used to check its value.
you send data
data: JSON.stringify({
'blue': window.glbBlue,
'eg2': 'eg3'
})
means your action receive two parameter blue and eg2 but you received only one parameter json which is not supplied. For this reason json is null.
you can change public ActionResult submitForm(string json) {} To public ActionResult submitForm(string blue,string eg2) {}.
OR
data: JSON.stringify({json: "something" })
Below is my AJAX GET request that is trying to pass few parameters including a javascript object to a mvc controller but the object is always received as null:
var sort = { column: 'UserName', order: 'desc' };
var sortParameter = JSON.stringify(sort);
$.ajax({
url: '#Url.Action("GetUsers", "Account")',
cache: false,
type: 'GET',
contentType: 'application/json; charset=utf-8',
data: { skipRecords: vm.pageIndex * 1000, sortParam: sortParameter },
success: function (data) {
}
});
The controller method looks like below:
[HttpGet]
public JsonResult GetUsers(int skipRecords, Sort sortParam, string userName = null)
{
}
Also below is the Sort class defined:
public class Sort
{
public string column { get; set; }
public string order { get; set; }
}
If I dont use JSON.stringify and pass just the javascript object, below is the request that gets sent:
GET /Account/GetUsers?skipRecords=0&sortParam%5Bcolumn%5D=UserName&sortParam%5Border%5D=desc&_=1408990051727 HTTP/1.1
You're probably looking for:
var sortParameter = { column: 'UserName', order: 'desc' };
$.ajax({
url: '#Url.Action("GetUsers", "Account")',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify({
skipRecords: vm.pageIndex * 1000,
sortParam: sortParameter }),
success: function (data) {
}
});
The reason your code doesn't work is because if you don't JSON.stringify the entire result, it is passed as a querystring encoded. You can't pass JSON as a value in a querystring encoded value.
Querystring encoded (Post or Get) looks like: a=1&b=2&c=3
So your querystring would look like skipRecords=5&sortParam={column:'UserName',order:'desc' }
MVC Won't double decode querystring and json.
Use POST and prepend [FromBody] to your 'Sort' object parameter in your action method.