cannot pass paramerters as JSON to mvc controller - c#

I am trying to pass an id and an object which has four properties to an action controller but unfortunately it is not getting through and I get the following error.
The parameters dictionary contains a null entry for parameter 'batchID' of non-nullable type 'System.Int32' for method 'System.Web.Mvc.JsonResult GetItems(Int32, Ebiquity.Reputation.Neptune.Web.Models.MyWorkFilterModel)' in 'Ebiquity.Reputation.Neptune.Web.Controllers.MyWorkController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.
Parameter name: parameters
The JSON being passed is:
{
"batchID": 21610,
"filter":
{
"issueNo": "1",
"messageNo": "2",
"itemDate": "Wed, 05 Feb 2014 00:00:00 GMT",
"mediaName":"3"
}
};
The ajax call:
self.GetItems = function (batchID, issueNo, messageNo, itemDate, mediaName) {
var filter = {
issueNo: issueNo,
messageNo: messageNo,
itemDate: itemDate,
mediaName: mediaName
};
$.ajax({
type: "GET",
url: "/MyWork/GetItems",
data: JSON.stringify({
batchID: batchID,
filter: filter
}),
dataType: "json",
success: function (result) {
self.Items([]);
if (result.Items != null) {
var tempItems = ko.mapping.fromJS(result.Items, mappingOptions);
self.Items.push.apply(self.Items, tempItems());
}
}
});
};
The controller:
[HttpGet]
public JsonResult GetItems(int batchID, MyWorkFilterModel filter)
{
using (var rep = new WorkRepository(CurrentUser))
{
return Json(rep.GetBatch(batchID, filter), JsonRequestBehavior.AllowGet);
}
}
The filter model:
public class MyWorkFilterModel
{
public int? IssueNo { get; set; }
public int? MessageNo { get; set; }
public string MediaName { get; set; }
public DateTime? ItemDate { get; set; }
}

You have to change type of your AJAX call to POST instead of GET. Data parameters will not be send with GET requests.

Looks like your batchID is null. Either set it as 0 in javascript or make it nullable in action
[HttpGet]
public JsonResult GetItems(int? batchID, MyWorkFilterModel filter)
{
}

You may try to make IssueNo and MessageNo as integers instead of strings. And use POST instead of GET.
If you have to use GET, you may pass the parameters as a part of the url only!

We have a lot of discussions here like this (see the below link)
Posting JSON data via jQuery to ASP .NET MVC 4 controller action
Try like below Ajax DataType:
self.GetItems = function (batchID, issueNo, messageNo, itemDate, mediaName) {
var filter = {
issueNo: issueNo,
messageNo: messageNo,
itemDate: itemDate,
mediaName: mediaName
};
$.ajax({
type: "POST",
url: "/MyWork/GetItems",
dataType: 'text',
data: "param=" + JSON.stringify({
batchID: batchID,
filter: filter
}),
success: function (result) {
self.Items([]);
if (result.Items != null) {
var tempItems = ko.mapping.fromJS(result.Items, mappingOptions);
self.Items.push.apply(self.Items, tempItems());
}
}
});
};
The controller
[HttpPost]
public JsonResult GetItems(String Param)
{
}

As mentioned by Semao, if you want that kind of JSON you need to use POST. Since your posting the JSON in that way, I guess you just have a typo and intend to use POST.
If you really want GET, you need to pass the values in the URL.
In your case, youneed to add:
[FromUri]
before the objects.
Example:
public class QueryObj
{
public int Id { get; set; }
public string Name { get; set; }
}
public Result Get([FromUri] QueryObj queryObj)
{...}
http://.../query?Id=1&Name=test

I was missing the contenttype property of the ajax call and instead of GET I used POST and it worked.
$.ajax({
type: "POST",
url: "/MyWork/GetItems",
data: JSON.stringify({
batchID: batchID,
filter: filter
}),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (result) {
}
});

Related

ValidateAntiForgeryToken in asp.net mvc 5.0 - how to pass array of objects with JSON and ajax

It seems that ValidateAntiForgeryToken attribute prevents the data from being parsed properly when passed to MVC Controller, the code below works when I remove the ValidateAntiForgeryToken attribute but does not work with it, all the parameters in the controller action are passed except array of translations.
Please advise on how to pass array of objects while utilizing ValidateAntiForgeryToken attribute, is it even possible?
This is my code
C#
[HttpPost]
[ValidateAntiForgeryToken]
public void AddComment( string code, string type, string ecomment, IEnumerable<CommentTranslation> translations)
{
//do something later
}
CommentTranslation is
public class CommentTranslation
{
public string LangId { get; set; }
public string LangName { get; set; }
public string Translation { get; set; }
}
js
addComment: function (ecomment, type, translations) {
var data = {
code: '',
type: type,
ecomment: ecomment,
translations: translations
};
var url = 'CommentsAjax/AddComment';
return comments.repository.postDataWithToken(data, url);
},
postDataWithToken: function (data, url) {
return $.ajax({
type: 'POST',
traditional: true,
contentType: 'application/x-www-form-urlencoded; charset=utf-8',
data: comments.repository.addAntiForgeryToken(data),
url: getServerPath() + url
});
}
addAntiForgeryToken: function (data) {
var token = $('input[name="__RequestVerificationToken"]').val();
data.__RequestVerificationToken = token;
return data;
},
Ended up using FormCollection that you can just generically pass anything into the Controller.

Why does my Ajax post have content when going to backend but my model and controller receive null

AJAX Post shows correct content in debugger but my controller and model receive null values.
I have changed my ajax post many ways. I have also just sent one string and had one string as my controller parameter. This worked, but I am looking to send the whole object.
var BuildContent = [{ 'Cal': Cal, 'BarLength': BarLength, 'Color':
Color }];
content = JSON.stringify(BuildContent);
$.ajax({
type: "POST",
url: "../Build/Build",
data: {'content':content},
ContentType: "application/json",
dataType: "json",
});
public class BuildController : Controller
{
[HttpPost]
public BuildContent Build (BuildContent content)
{
//BuildService.GetURG(data);
return content;
}
}
public class BuildContent
{
public string Cal { get; set; }
public string BarLength { get; set; }
public string Color { get; set; }
}
SO when the POST reaches the controller I am seeing [Cal = null , BarLength = null, Color = null]
Where as in the Chrome network debugger I see my content correctly. Such as
content: [{"Cal":"5.56","BarLength":"16\"","Color":"Black"}]
You're not sending an array of objects, only a single one. So there's no need to surround your object in an array initialiser.
Below I've created a JavaScript object and then converted it into JSON.
Try this and let me know how it goes.
var buildContent = {'Cal': 'Testing123...', 'BarLength': 'Noot Noot', 'Color': 'Red'};
var jsonData = JSON.stringify(buildContent);
$.ajax({
type: "POST",
url: "../Build/Build",
data: jsonData,
dataType: 'json',
contentType: 'application/json;'
});
EDIT:
Alternatively try sending the object in its entirety, without serializing it to JSON.
var buildContent = {'Cal': 'Testing123...', 'BarLength': 'Noot Noot', 'Color': 'Red'};
$.ajax({
type: "POST",
url: "../Build/Build",
data: buildContent
});

Unable to pass values to MVC Controller via AJAX

I have an MVC controller which takes an int and a complex object
[HttpPost]
public async Task<JsonResult> AddComment(int ticketId, TicketReply ticketReply)
Even if I take out the object, I can't seem to pass a simple value. Here's what the AJAX call looks like
var dataObject = {
ticketId: ticketId //, ticketReply: { Attachements: attachements }
};
$.ajax({
url: $('#updateTicketURL').val(),
data: dataObject, //, //JSON.stringify(dataObject), //JSON.stringify(dataObject),
type: 'POST',
//dataType: 'JSON',
contentType: 'application/json',
success: function (data) {
console.log(data);
}
})
I have tried every combination of JSON.stringyfy etc. but I never seem to get the value. Even if I replace with static values it never seems to work.
You need an object model that matches the data being sent
public class DataObject {
public int ticketId { get; set; }
public TicketReply ticketReply { get; set; }
}
next you update the controller action to expect the data using the [FromBody] attribute so that the model binder can create and populate the sent data
[HttpPost]
public async Task<JsonResult> AddComment([FromBody]DataObject dataObject) {
int ticketId = dataObject.ticketId;
TicketReply ticketReply = dataObject.ticketReply;
//...
}
Finally you need to send the data correctly from the client.
var dataObject = {
ticketId: ticketId ,
ticketReply: { Attachements: attachements }
};
$.ajax({
url: $('#updateTicketURL').val(),
data: JSON.stringify(dataObject),
type: 'POST',
dataType: 'JSON',
contentType: 'application/json',
success: function (data) {
console.log(data);
}
});

pass value to controller by using ajax

I want to pass value from view to controller by using ajax.
<button onclick="addCommentByAjax()" >Save</button>
My script:
function addCommentByAjax() {
$.ajax({
type: "POST",
url: '/Survey/DoDetailSurvey',
data: {
choiceId: "1"
}
});
}
Controller:
[HttpPost]
public ActionResult DoDetailSurvey(SurveyViewModel model, string choiceId)
{
//
}
but choiceId always null
Change couple of things.
First assign an id or class to your button.Second remove inline onclick function and use ajax click function.Then specify the request type as Post.
$('#btnComment').click(function () {
var choiceId = $('#YourChoiceId').val();
$.ajax({
url: '/Survey/DoDetailSurvey',
data: { 'choiceId' : choiceId},
type: "post",
cache: false,
success: function (response) {
//do something with response
},
error: function (xhr, ajaxOptions, thrownError) {
alert('error occured');
}
});
});
Then your controller should look like this
[HttpPost]
public ActionResult DoDetailSurvey(string choiceId)
{
//
}
I don't know how you are populating your viewmodel,so I purposely removed them and shown an working example.
In case you want to pass viewmodel you should construct your data object like this:
var data = {};
data.Property1 = some val;
data.Property2 = "some val";
$.post('/Survey/DoDetailSurvey', data);
Sample structure of SurveyViewModel I assume:
public class SurveyViewModel
{
public int Property1 { get; set; }
public string Property2 { get; set; }
}
Since there are two parameter in your controller, you need to identify them both form the client side. Further, you should specify the contentType.
You spread the payload like so:
function addCommentByAjax() {
var payload = {
model: {
// whatever properties you might have
},
choiceId: 1
};
$.ajax({
type: "POST",
url: '/Survey/DoDetailSurvey',
contentType: 'application/json',
data: JSON.stringify(payLoad)
});
}
function addCommentByAjax() {
$.ajax({
type: "POST",
url: '/Survey/DoDetailSurvey?choiceId=1'
}
});
}
You can also pass like this
or for more parameters
function addCommentByAjax() {
$.ajax({
type: "POST",
url: '/Survey/DoDetailSurvey?choiceId=1&Name=Arun'
}
});
}

JS hardcode ajax data: parameter works. JS Variable does not

======================
Part 2
MVC controler's field1 always has null (Post([FromBody] TestModel field1) ) null values if I use JSON.stringify(MyDdata). Even on the simplest JSON strings.
I used an XML to JSON convert to make sure my JSON data was correct. (I still need to get to know JSON.) I would think the following would be easily consume by the MVC controller but the input parameter field1 is null. At the least, TestStrng & TestStrng2 should have values.
The controller isn't crashing but it isn't understanding the JSON either.
Why doesn't the MVC Controler know the JSON class?
//JavaScript
var MyDdata =
{
"TestModel": {
"TestStrng": "Scott",
"TestStrng2": "SomethingElse",
"Usr": { "UsrToken": "aaaa" },
"LstSubClass": {
"SubClass": [
{ "FirstName": "Beth" },
{ "FirstName": "Julie" },
{ "FirstName": "John" }
]
}
}
}
sdata = JSON.stringify(MyDdata);
$.ajax({
type: 'post',
url: serviceUrl,
cache: false,
data: sdata,
dataType: "json",
}).done(function (data) {
//C# Class
public class Usr
{
public string UsrToken { get; set; }
}
public class SubClass
{
public string FirstName { get; set; }
}
public class TestModel // Main\Master Class
{
public string TestStrng { get; set; }
public string TestStrng2 { get; set; }
public List<SubClass> LstSubClass = new List<SubClass>();
private Usr _Usr = new Usr();
public Usr oUsr
{
get { return _Usr; }
set { _Usr = value; }
}
}
//MVC Controller
[System.Web.Http.Description.ResponseType(typeof(TestModel))]
public HttpResponseMessage Post([FromBody] TestModel field1)
{
// ...
}
//XML Data
<TestModel>
<TestStrng>Scott</TestStrng>
<TestStrng2>SomethingElse</TestStrng2>
<Usr>
<UsrToken>aaaa</UsrToken>
</Usr>
<LstSubClass>
<SubClass><FirstName>Beth</FirstName></SubClass>
<SubClass><FirstName>Julie</FirstName></SubClass>
<SubClass><FirstName>John</FirstName></SubClass>
</LstSubClass>
</TestModel>
JSON Data
{
"TestModel": {
"TestStrng": "Scott",
"TestStrng2": "SomethingElse",
"Usr": { "UsrToken": "aaaa" },
"LstSubClass": {
"SubClass": [
{ "FirstName": "Beth" },
{ "FirstName": "Julie" },
{ "FirstName": "John" }
]
}
}
}
======================
Part 1
I am trying to learn Web API in C# and have spent a day on this one problem. The problem is in JavaScript with "data: ...".
hardcoded this works
Ajax data: {'TestStrng': 'one', 'TestStrng2': 'two' }
Below in the controller, as expected, the p_TestModel contains the values 'one' & 'two'.
public HttpResponseMessage Post(TestModel p_TestModel)
BUT
the data is NOT passed from JS to Controller if I use a variable like data: sdata.
I have tried tens of ways and many I am too embarrassed to write:
var sdata = "'TestStrng': 'one', 'TestStrng2': 'two'";
sdata = "'TestStrng': 'one'";
var jsonString = JSON.stringify(sdata);
JSON.stringify(sdata); {
'TestStrng': 'one',
'TestStrng2': 'two'
}, {
'TestStrng': 'one',
'TestStrng2': 'two'
}, {
field1: "hello"
},
data: {
sdata
},
'TestStrng': 'onetwo'
},
"{ 'TestModel': { 'TestStrng': 'one', 'TestStrng2': 'two' } }",
JSON.stringify(sdata),
sdata,
sdata = "'TestStrng': 'one', 'TestStrng2': 'two'";
data: {
TestModel,
sdata
},
Question
What am I doing wrong?
Why won't a JS variable send the data so the controller can see it as if it is hardcoded?
C# class
public class TestModel {
public string TestStrng { get; set; }
public string TestStrng2 { get; set; }
}
MVC Controller
[System.Web.Http.Description.ResponseType(typeof(TestModel))]
public HttpResponseMessage Post(TestModel p_TestModel)
{
// p_TestModel has correct values if hardcoded in JS.
// It is ALWAYS null if JS uses a variable (sData) to send it.
...
}
JavaScript
$.ajax({
type: 'post',
url: serviceUrl,
cache: false,
dataType: "json",
data: sdata, <<<<<<<<<<????
}).done(function (data) {
Create a javascript object and use that. This should work.
var sdata= { TestStrng :"Scott",TestStrng2:"SomethingElse" };
$.ajax({
type: 'post',
url: serviceUrl,
data: sdata
}).done(function (data) { console.log(data) });
If your view model is a flat view model without any complex navigational properties, the above code will work fine. But if you have complex properties on your view model, You need to convert the js object to a JSON String and set the contentType property
var model= { Name:"S",Address: { City:"Detroit"} };
$.ajax({
type: 'post',
url: serviceUrl,
data: JSON.stringify(model),
contentType: "application/json"
}).done(function (data) { console.log(data) });
Take a look at this answer explaining different approaches for sending data from your client js code to your web api endpoint.

Categories

Resources