I am trying to pass a single boolean value via ajax to a server API.
The API action is hitted but the parameter (shuffled) is false, though I am setting it to true via Ajax.
The api controller action is this:
[HttpPost("PostShuffled")]
public IActionResult PostShuffled([FromBody]bool shuffled)
{
userSession.Shuffled = shuffled;
return Ok();
}
My Ajax call is this:
function ChangeViewMode(el) {
if (el.id == "ViewShuffled") {
$.ajax({
url: "/api/Data/PostShuffled",
contentType: "application/json",
method: "POST",
data: JSON.stringify({ shuffled: true }),
success: function () { alert("ok"); }
});
}
}
My question is what am I doing wrong?
Ok I have solved the problem this way:
Defined a new class:
public class AjaxShuffled
{
public bool shuffled { get; set; }
}
Then in my controller changed:
[HttpPost("PostShuffled")]
public IActionResult PostShuffled([FromBody]AjaxShuffled s)
{
userSession.Shuffled = s.shuffled;
return Ok();
}
And now the value is passed correctly. I had to encapsulate the boolean into a class to make it work.
The problem is that shuffled is wrapped in an object instead of sent by itself. If you only want to send a boolean value, just send true or false itself: data: true or data: JSON.stringify(true) depending on how you've configured your web service to handle input formats for boolean. On the server side you should only need the [FromBody] descriptor on the API method parameter.
Related
The following is an example of the basic structure/goal:
javascript ajax structure:
helper = someBaseClass.extend({
init: function () {
},
makeRequest: function (options) {
return createAjaxObservable(
{
url: options.url,
data: JSON.stringify(options.data), //stringify is present
type: options.type,
contentType: 'application/json; charset=utf-8',
dataType: "json",
cache: false
});
}
});
server javascript request:
this.helper.makeRequest({ url: "/Session/RequestSomeInfo", type: "POST", data: { sessionId: options.sessionId, requestSomeInfo: { isActive: true } });
Request some arbitary info on sessionId, for all arbitary entities that are active.
I am using post here for testing purposes.
controller method:
[HttpPost]
public JsonResult RequestSomeInfo(Session sessionId, RequestSomeInfo request)
{
//implement api connection
//request some arbitary info on sessionid, for all arbitary entities that are active.
return CreateJson(true, new { Data = requestSomeInfoResponse.Data });
}
The above is the ideal solution.
I am aware it may not be possible.
What would be the best alternative solution?
I have omitted [FromBody]. [FromBody] I understand only will pass one parameter. I can get the above general structure to work, using[FromBody], but it'll only pass one parameter.
I have also tried using a wrapper class - which contains Session and RequestSomeInfo, then passing this wrapper class. This also works.
However, the problem being that RequestSomeInfo could be requesting different things across an extensive web app. For example, RequestSomeInfo could be RequestCustomerNames, RequestActivities, RequestSocialConnections, etc.
--> the objects I want to pass can get complex.
I can use abstraction, or generics to accomplish this. Using generics on the wrapper class works, and is so far the best solution, however, this isn't the ideal solution. Ideally, I want to implement the above basic goal and structure as closely as possible.
Ajax cannot map multiple complex types at the same time, it can only pass multiple basic types at the same time. A better approach is to create a ViewModel to refer to these two complex types.
Since you did not give the full ajax implementation code, I use jQuery's ajax as an example. The Session here is customized by default.
Here is the all model.
public class Session
{
public int sessionId { get; set; }
}
public class RequestSomeInfo
{
public bool isActive { get; set; }
}
public class ViewModel
{
public Session Session { get; set; }
public RequestSomeInfo RequestSomeInfo { get; set; }
}
The Ajax code is as follows (it put in Index.cshtml).
$(function () {
$.ajax({
url: '/Session/RequestSomeInfo',
type: 'post',
data: {
session: {
sessionId: '123'
},
requestSomeInfo: { isActive: true }
},
success: function (data) {
console.log(data)
},
error: function () {
}
})
})
The controller is changed like this.
[HttpPost]
public JsonResult RequestSomeInfo(ViewModel viewModel)
{
return Json(viewModel);
}
And you can get this result.
I am trying to send data with AJAX to MVC Controller method, but I don't know what am I doing wrong.
Here is the AJAX call
$.ajax({
type: 'POST',
url: invokingControllerActionUrl,
data: "it is just a simple string",
success: function (data) {
window.location.href = link;
}
});
And here is the controller method. It is invoked, but the parameter is always null.
public IActionResult OnPostTest([FromBody] string stringValue)
{
// stringValue is always null :(
}
Change you ajax call to this
$.ajax({
type: 'POST',
url: invokingControllerActionUrl, // Confirm the Path in this variable Otherwise use #Url.Action("OnPostTest", "InvokingController")
data: {stringValue: "it is just a simple string"},
success: function (data) {
window.location.href = link;
}
});
And remove the [FromBody]. ALso its better to define type post. Not necessary though
[HttpPost]
public IActionResult OnPostTest( string stringValue)
{
// stringValue is always null :(
}
Depending on what Content-Type you are sending from JS, you might need to encode your string properly, as a form-value
...
data: 'stringValue="it is just a simple string"',
...
or e.g. JSON:
...
data: '{stringValue: "it is just a simple string"}',
...
See also this discussion
I haven't found an easy way to pass a string of unformatted data via parameter, unfortunately. According to this answer, you can do the following:
public IActionResult OnPostTest()
{
Stream req = Request.Body;
req.Seek(0, System.IO.SeekOrigin.Begin);
string stringValue = new StreamReader(req).ReadToEnd();
...
// process your stringValue here
...
}
How can I return a class object from Ajax in asp.net MVC....???
Example:
Ajax call from html:
$.ajax({
type: 'POST',
url: '/Tutorial/Web/AlignmentRule/GetAlignmentDetails',
data: { alignmentRuleId: alignmentRuleId },
success:
function (data) {
alert(data.Id);
alert(data.alignmentData.Id);
$("#ruleName").val(data.alignmentData.Name);
$("#level").val(data.alignmentData.Id);
},
error:
function () {
alert("Server Error!!!!");
},
dataType: 'JSON',
async: false
});
and Action method in contorller is:
public virtual JsonResult GetAlignmentDetails(int alignmentRuleId)
{
var alignmentData = _allignmentRuleRepository.GetAlignmentById(alignmentRuleId);
return Json( alignmentData );
}
And I want to return a list of alignmentRule class objects also....
you can compose your return object as you want, for example, create a ViewModel as decorator to hold everything you want to pass, like:
var json = new JsonViewModel() {
alignmentData = alignmentData,
rules = yourRules
};
return Json(json);
The error is thrown because by default MVC framework does't allow you to respond to an HTTP GET request with a JSON (because of security reasons).
In order to make it work, when you retrurn Json in your action, you need to specify JsonRequestBehavior.AllowGet
[HttpPost]
public virtual JsonResult GetAlignmentDetails(int alignmentRuleId)
{
var alignmentData = _allignmentRuleRepository.GetAlignmentById(alignmentRuleId);
return Json( alignmentData, JsonRequestBehavior.AllowGet);
}
EDIT
Annotate your action with [HttpPost] attribute.
For further investigation on this topic check this article
Following is my ajax call
$.ajax({
type: "GET",
url: "https://localhost/api/Client",
data: JSON.stringify({"SortExpression":"clientName","SortDirection":"desc"}),
contentType: "application/json; charset=utf-8",
async: false,
cache: false,
dataType:'json',
error: function (data) {
alert("hi error buddy")
},
success: function (response) {
if (response) {
//todo
}
}
});
And my controller
public List<Customer> Get([FromUri] SortFilter filter)
{
}
and my model
public class SortFilter
{
public string SortExpression
{
get; set;
}
public string SortDirection
{
get; set;
}
}
but my contoller always takes the parameters as NULL. where am I going wrong ?
You're supplying a value, but not a key. So while the model binder may be able to discern what a SortFilter is, it has no way of knowing what filter is.
Try wrapping the object and giving it a key name. Perhaps something like this:
JSON.stringify({"filter":{"SortExpression":"clientName","SortDirection":"desc"}})
GET requests are performed on the query string, which should not be JSON encoded. POST, and PUT data may be JSON encoded, but not GET. The reason your parameter is null is because the query string is a single string with no parameter name.
replace:
data:JSON.stringify({"SortExpression":"clientName","SortDirection":"desc"})
with
data:{"SortExpression":"clientName","SortDirection":"desc"}
You can check the WebAPI call directly by typing in the full URL to the web API method
https://localhost/api/Client?SortExpression=clientName&SortDirection=desc
This will allow you to debug your data retriever, and page separately which should make the whole process much easier.
I am using revealing module pattern and knockout to bind a form. When data is entered in that form(registration), it needs to be posted back to MVC4 web method.
Here is the Jquery code
/*
Requires JQuery
Requires Knockout
*/
op.TestCall = function () {
// Private Area
var _tmpl = { load: "Loading", form: "RegisterForm"};
var
title = ko.observable(null)
template = ko.observable(_tmpl.load),
msg = ko.observable(),
postData = ko.observable(),
PostRegistration = function () {
console.log("Ajax Call Start");
var test = GetPostData();
$.ajax({
type: "POST",
url: obj.postURL, //Your URL here api/registration
data: GetPostData(),
dataType: "json",
traditional: true,
contentType: 'application/json; charset=utf-8'
}).done(Success).fail(Failure);
console.log("Ajax Call End");
},
GetPostData = function () {
var postData = JSON.stringify({
dummyText1: dummyText1(),
dummyText2: dummyText2(),
});
return postData;
}
return {
// Public Area
title: title,
template: template,
dummyText1: dummyText1,
dummyText2: dummyText2
};
}();
The controller code is simple as per now
// POST api/registration
public void Post(string data)
{
///TODO
}
When i am trying to, capture the data (using simple console.log) and validate it in jslint.com, it's a valid Json.
I tried hardcoding the data as
data: "{data: '{\'name\':\'niall\'}'}",
But still i get as null, in my web method.
Added the tag [System.Web.Script.Services.ScriptMethod(UseHttpGet = false, ResponseFormat = System.Web.Script.Services.ResponseFormat.Json)] to my Post method in controlled, but still no fruitful result
Even tried JSON.Stringify data: JSON.stringify(data) but still i get null in my web-method.
I am not able to figure out the solution.
Similar issue was found # this link
http://forums.asp.net/t/1555940.aspx/1
even Passing parameter to WebMethod with jQuery Ajax
but didn't help me :(
MVC and WebApi uses the concept of Model Binding.
So the easiest solution is that you need to create a Model class which matches the structure of the sent Json data to accept the data on the server:
public void Post(MyModel model)
{
///TODO
}
public class MyModel
{
public string DummyText1 { get; set; }
public string DummyText1 { get; set; }
}
Note: The json and C# property names should match.
Only escaped double-quote characters are allowed, not single-quotes, so you just have to replace single quotes with double quotes:
data: "{data: '{\"name\":\"niall\"}'}"
Or if you want to use the stringify function you can use it this way:
data: "{data: '" + JSON.stringify(data) + "'}"