Writing a web api project and one of the parameters (which is a json array) on my method is coming into the api null. The jquery I'm making the call with looks like this:
<script>
$(document).ready(function () {
$('#btnSubmit').click(function () {
var jsRequestAction = {
appId: 'appName',
custId: 'custId',
oprId: 'oprId',
businessProcess: 'Requisition',
action: 'Approve',
actionKeys: [
'blah blah 1',
'blah blah 2',
'blah blah 3'
]
};
$.ajax({
type: "POST",
content: "json",
url: "http://localhost/api/appName/custId/oprId",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ requestAction: jsRequestAction })
});
});
});
</script>
My web api method looks like this:
public IList<ResponseAction> ActionCounter(string appName, string custCode, string custUserName, RequestAction requestAction)
{
IList<ResponseAction> actionResponseList = new List<ResponseAction>();
var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["conn"].ConnectionString);
conn.Open();
try
{
foreach (string s in requestAction.actionKeys)
{
var command = new SqlCommand
{
CommandText = "Sql statement",
Connection = conn
};
command.ExecuteNonQuery();
var reply = new ResponseAction();
reply.responseActionKey = s;
reply.responseMessage = "Success";
actionResponseList.Add(reply);
}
return actionResponseList;
}
finally
{
conn.Close();
conn.Dispose();
}
}
RequestAction model:
public class RequestAction
{
public string appId { get; set; }
public string custId { get; set; }
public string oprId { get; set; }
public string businessProcess { get; set; }
public string action { get; set; }
public string[] actionKeys { get; set; }
public string actionKey { get; set; }
}
When I debug, I step through the method and when I get to the foreach loop, I get a null object reference. Looking in my locals section, all my properties for requestAction are null. I have tried prefixing the object with the [FromBody] tag to no avail after reading a few related articles. Any help would be appreciated.
I found the answer to my question HERE. It was a matter of changing this:
$.ajax({
type: "POST",
content: "json",
url: "http://localhost/api/appName/custId/oprId",
contentType: "application/json; charset=utf-8",
data: JSON.stringify({ requestAction: jsRequestAction })
});
to this:
$.ajax({
type: "POST",
content: "json",
url: "http://localhost/api/appName/custId/oprId",
data: jsRequestAction
});
Otherwise, the data won't bind to my model in the controller and everything will be nulled out.
You need to make sure the object server side matches the object you are creating client side so that the request can be serialized directly into the object.
So your action method will look like this:
public IList<ResponseAction> ActionCounter(RequestAction requestAction)
{
// Do stuff
}
Where RequestAction should match the javascript object you are creating.
Related
I am having a hard time posting a list of arrays from my view to the controller. Every other value is coming through.
Can someone spot what is wrong with my code?
Controller:
public ActionResult SaveProgress(BBCRMSurveyVM model)
{
try
{
return Json(new { success = true });
}
catch (Exception e)
{
return Json(new { success = false, msg = e.Message });
}
}
Main view model:
public string ImplementationProcessFeelWasSuccessful { get; set; }
public string ImplementationProcessAdviceOtherFederations { get; set; }
public List<AdditionalTechnologyVM> AdditionalTech = new List<AdditionalTechnologyVM>();
AdditionalTechVM:
public class AdditionalTechnologyVM
{
public string PlatformName { get; set; }
public string BusinessPurpose { get; set; }
public bool? FullyIntergrated { get; set; }
public bool? PartiallyIntergrated { get; set; }
}
JS file:
function onAddButtonClickEvent() {
additionaltechs.push({
'PlatformName': platformNameAT,
'BusinessPurpose': businessPurposeAT,
'FullyIntergrated': intergrated == "Fully" ? true : false,
'PartiallyIntergrated': intergrated == "Partially" ? true : false
});
}
function SaveProgress() {
var formData = $('#wizard').serializeArray();
//if (additionaltechs.length > 0) {
// for (var x = 0; x < additionaltechs.length; x++) {
// formData[formData.length] = { name: "AdditionalTech", value: JSON.stringify(additionaltechs[x]) };
// }
//}
formData[formData.length] = { name: "AdditionalTech", value: additionaltechs };
$.each(formData, function (index, field) {
if (field.name.search('Budget') > 0) {
field.value = field.value.replace('$', '').replace(/,/g, '');
}
});
formData = JSON.stringify(formData);
console.log(formData);
$.ajax({
url: '/save-progress',
contentType: 'application/json; charset=utf-8',
type: 'POST',
data: formData,
dataType: 'json',
success: function () {},
error: function () {}
});
}
The output in the console:
The list count is always 0?
I think you made this more complicated than you needed it to be. :)
Ultimately, it looks like your controller method is taking a single model, not an array. Thus, I would suspect to see the JSON you send look like this:
{
"ImplementationProcessFeelWasSuccessful" : "",
"ImplementationProcessAdviceOtherFederations" : "",
"AdditionalTech" : [...]
}
If it should be a single item being sent, then I'd expect your code to be like this:
function SaveProgress() {
var formData =
{
ImplementationProcessFeelWasSuccessful : $('#wizard #val1').val(),
ImplementationProcessAdviceOtherFederations : $('#wizard #val2').val(),
AdditionalTech : additionaltechs
};
formData = JSON.stringify(formData);
console.log(formData);
$.ajax({
url: '/save-progress',
contentType: 'application/json; charset=utf-8',
type: 'POST',
data: formData,
dataType: 'json',
success: function () {},
error: function () {}
});
}
However, you are sending an array of items up and that makes no sense here.
Ended up sending the list as a JSON string & receiving it also as a string. In the controller I using the JsonConvert.DeserializeObject method like this:
var additionalTechs = JsonConvert.DeserializeObject<List<AdditionalTechnologyVM>>
(model.AdditionalTech);
have tried the methods found but still cannot seem to tackle the issue.
am passing a list of object via Jquery Aja but it seems that the controller is receiving null values (it is recognizing the list count fine).
the jquery code is as follows:
var xmlids = Array();
for (var i = 0; i < orderId.length; i++) {
var xdata = {
"XmlOid": "" +orderId[i] + "",
"CourierCompany": $("#CourierCompany_"+orderId[i]).val() ,
"CourierService": $("#CourierService_" + orderId[i]).val(),
"StoreId" : storeId
};
xmlids.push(xdata);
}
var data = { invoices: xmlids };
$.ajax({
url: purl,
type: "POST",
dataType: "json",
//contentType: "application/json;",
async: false,
data: data,
The controller param is :
public JsonResult ProcessSaleOrder(List<XMLInvoiceGeneration> invoices)
the object is as follows:
public class XMLInvoiceGeneration
{
public Int64 XmlOid { get; set; }
public string CourierCompany { get; set; }
public string CourierService { get; set; }
public Int64? StoreId { get; set; }
}
any help appreciated.
I tried to replicate your problem.
I created a new ASP.NET MVC web application, and in the Home controller's Index view, I added the following
<input type="button" id="send" value="Send" />
#section scripts{
<script type="text/javascript">
$(function () {
$("input#send").on("click", function () {
var xmlids = Array();
for (var i = 0; i < 2; i++) {
var xdata = {
"XmlOid": 1,
"CourierCompany": "TempData",
"CourierService": "Temp",
"StoreId": 2
};
xmlids.push(xdata);
}
var data = { invoices: xmlids };
$.ajax({
url: "/Home/ProcessSaleOrder",
type: "POST",
dataType: "json",
async: false,
data: data
});
});
})
</script>
}
I basically created some temp data, but trying to still use your original idea. My controller looks like this:
[HttpPost]
public ActionResult ProcessSaleOrder(List<XMLInvoiceGeneration> invoices)
{
return new EmptyResult();
}
When I click the button, and hit the breakpoint in the controller, the invoices parameter contains 2 items, both with the values I set in the JavaScript code. I'm not sure why your code isn't working, but maybe you can use mine as a template to help you narrow down what the issue is.
Try this
uncomment //contentType: "application/json;",
And send data with JSON.stringify(data)
data: JSON.stringify(data)
PS: Best practice for url : url: "#Url.Action("method","controller")"
I had the same issue on sending a List to the controller. After a lot of effort, I found the reason why it is sending as null. It's the fields with Return Type(Class) that are not added with {get; set; }
$.ajax({
url: "/Home/CreateTasks",
data: ko.toJSON({Id: this.Id, tasks: objList }),
type: "POST",
dataType: "json",
processData: true,
contentType: "application/json; charset=utf-8",
success: data => {
}
And my Model Class is:
After
public class TaskFields
{
public string Title { get; set; }
public string Activity { get; set; }
}
public class CreateTaskInput
{
public int Id { get; set; }
public TaskFields TaskProperties { get; set; }
}
Before it was:
public class TaskFields
{
public string Title;
public string Activity;
}
public class CreateTaskInput
{
public int Id;
public TaskFields TaskProperties;
}
And My Controller Method is:
[HttpPost]
public JsonResult MethodName(int Id, List<CreateTaskInput> tasks)
{
}
I am not sure this answer will help you. But it may help someone who has a similar mistake. Thanks!
Add [FromBody] to the parameters in action
[HttpPost]
public ActionResult ProcessSaleOrder([FromBody] List<XMLInvoiceGeneration> invoices)
{
return new EmptyResult();
}
I have an .aspx page that we are loading UserControls into dynamically at runtime. Each user control has some sort of textbox or combo or some other control. This all works fine. when we go to read the values out of the controls when the user presses search, we cannot do this directlly from C# code behind because the page does not know they are there. my solution is to read the values with JQuery and make an ajax call where I can set the values in a session variable for use when the user gets to the next page. I am having trouble with the JSon specifically.
I keep getting the error:
{"Message":"Cannot convert object of type \u0027System.String\u0027 to type \u0027System.Collections.Generic.IDictionary`2[System.String,System.Object]\u0027","StackTrace":"
I find all the controls using .each and get the values for the JSon call:
function SaveFields() {
var data = [];
//get Search field criteria
$('[id^=Search_ucField_]').each(function (index, value) {
var field = $(this);
var id = $(this).attr('id').split("_")[2];
var fieldValue = $(this).val();
if (field.is('input')) {
var item = {};
item['FieldID'] = id;
item['Criteria'] = fieldValue;
item['IsActive'] = 1;
item['FieldCategoryID'] = '1';
item['ControlPath'] = '~/Controls/Search/TextBox.aspx';
item['CategoryID'] = 1;
data.push(item);
}
});
$.ajax({
url: '/Ajax/Ajax.aspx/DoSearch',
type: 'POST',
data: JSON.stringify(data),
datatype: 'json',
contentType: 'application/json',
success: function (msg) {
console.log(msg);
},
error: function (xhr, textStatus, errorThrown) {
alert('Error! Status = ' + xhr.status);
}
});
}
Here is the object I am trying to deserialize into:
[DataContract]
public class SearchFields
{
[DataMember]
public List<SearchField> Field { get; set; }
}
[DataContract]
public class SearchField
{
[DataMember]
public string FieldID { get; set; }
[DataMember]
public bool IsActive { get; set; }
[DataMember]
public string Criteria { get; set; }
[DataMember]
public int FieldCategoryID { get; set; }
[DataMember]
public string ControlPath { get; set; }
}
Here is the WebMethod
[WebMethod]
public static string DoSearch(string Fields)
{
var sf = new SearchFields();
sf = JsonConvert.DeserializeObject<SearchFields>(Fields);
//save into session variable
SVars.NewUISearch.LastSearchFields = sf;
string x;
x = "until this works, this is a static response";
return x;
}
finally, here is a sample of the JSon that is being sent:
[{"FieldID":"52","getCriteria":"Bobs your uncle","IsActive":1,"FieldCategoryID":"1","ControlPath":"~/Controls/Search/TextBox.aspx"}]
Where am I going wrong here? Thanks in advance!
I couldn't get $('form').serialize() to work so this is what I did. Make sure the properties you define in model represent the properties in your model and are strongly typed.
var model = {
MyString: $("#MyString").val(),
MyNumber: $("#MyNumber").val(),
IsCheck: $("CHK").val()
};
$.ajax({
type: "POST",
url: "/Testing/Index",
contentType: "application/json",
data: JSON.stringify(model),
dataType: "json",
success: function (data) {
// Good stuff
},
error: function (data) {
// Bad stuff
}
})
I am learing using jquery ajax to hander the JSON..i writre a demo code.
HTMLCODE
$(function () {
$("#add").click(function () {
var json = '{ "str":[{"Role_ID":"2","Customer_ID":"155","Brands":"Chloe;","Country_ID":"96;"}]}';
$.ajax({
url: "func.aspx/GetJson",
type: "POST",
contentType: "application/json",
dataType: 'json',
data: json,
success: function (result) {
alert(result);
},
error: function () {
alert("error");
}
});
});
});
<div>
<input type="button" value="add" id="add" />
</div>
i got a input and bind a script function to it, now the proble is comeing..
my C# functiong like that.
[WebMethod]
public static string GetJson(object str)
{
return str.ToString();//good for work
}
[Serializable]
public class TestClass
{
public TestClass()
{
}
public TestClass(string role_id, string customer_id, string brands, string countryid)
{
this.Role_ID = role_id;
this.Customer_ID = customer_id;
this.Brands = brands;
this.Country_ID = countryid;
}
public string Role_ID { get; set; }
public string Customer_ID { get; set; }
public string Brands { get; set; }
public string Country_ID { get; set; }
}
when i user
public static string GetJson(object str)
everything is so good.~~ no error at all
but . when i try to use my own class TestClass.
firebug tell me that
"Type 'TestClass' is not supported for deserialization of an array."
.any body can give me help:XD
This is how it looks when I do this using a WCF webservice. Hopefully it can help you. Let me know if you need any further clarification.
Script:
var data = {
emailAddress: emailAddress,
firstName: firstName,
lastName: lastName,
groups: groups
};
$.ajax({
type: "POST",
url: Client.svc/Subscribe",
data: JSON.stringify(data),
dataType: "json",
contentType: "application/json; charset=utf-8",
processdata: true,
success: function (result) {
//do something
}
});
Service:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[BasicHttpBindingServiceMetadataExchangeEndpoint]
public class Client : IClient
{
public bool Subscribe(string emailAddress, string firstName, string lastName, string[] groups)
{
//do something
return true;
}
}
I have a bit of code where I'm trying to send a Viewmodel back to the controller using Ajax post. If I write the code one way, it passes correctly, and another way it returns null or 0 values within the viewmodel.
The way that works:
$(document).ready(function () {
$(".boxItem").change(function (event) {
var url = "/Search/GetBoxChangeInfo";
$.post(url, #Html.Raw(Json.Encode(Model)), function (data) {
$("#column-1").html(data);
});
});
});
And the way that returns null values:
$(document).ready(function () {
$(".boxItem").change(function (event) {
var url = "/Search/GetBoxChangeInfo";
$.post(url, { json: #Html.Raw(Json.Encode(Model)) }, function (data) {
$("#column-1").html(data);
});
});
});
i need to use it the second way because I need to also pass parameters back about the selected value and ID, so it will look something like:
$(document).ready(function () {
$(".boxItem").change(function (event) {
var str = $(this).attr('id');
var num = $(this).val();
var url = "/Search/GetBoxChangeInfo";
$.post(url, { json: #Html.Raw(Json.Encode(Model)), id : str, selected : num }, function (data) {
$("#column-1").html(data);
});
});
});
My controller looks like this btw:
[HttpPost]
public ActionResult GetBoxChangeInfo(EventViewModel json)
{
//stuff
}
EDIT - as requested, here is EventViewModel structure
[JsonObject(MemberSerialization.OptIn)]
public class EventViewModel
{
public int EventNumber { get; set; }
public List<EventItemsViewModel> EventItems { get; set; }
public List<LocationViewModel> Locations { get; set; }
public int StartLocationID { get; set; }
public bool Outbound { get; set; }
public List<int> SelectedEvents { get; set; }
public List<DurationsViewModel> Durations { get; set; }
}
Anyone know why this might be happening? Is there a limit to home much can be sent to the controller this way - it is quite a complex viewmodel, so wondered if that could be someting to do with it.
Thanks
Like this:
$(document).ready(function () {
$('.boxItem').change(function (event) {
var str = $(this).attr('id');
var num = $(this).val();
var url = '#Url.Action("GetBoxChangeInfo", "Search")';
$.ajax({
url: url,
contentType: 'application/json',
data: JSON.stringify({
json: #Html.Raw(Json.Encode(Model)),
id: str,
selected: num
}),
success: function(data) {
$("#column-1").html(data);
}
});
});
});
Things to notice:
contentType: 'application/json'
JSON.stringify to convert the object into a JSON string
var url = '#Url.Action("GetBoxChangeInfo", "Search")'; to avoid hardcoding urls
Is there a limit to home much can be sent to the controller this way - it is quite a complex viewmodel, so wondered if that could be someting to do with it.
Yes there is and it's 1000 HTTP Collection keys and you can configure that yourself in the web.config. Try setting the value to 4000 first, then you can lower it a bit if you like. Try this:
<appSettings>
<add key="aspnet:MaxHttpCollectionKeys" value="4000" />
</appSettings>
Use this
http://api.jquery.com/jQuery.post/
$.ajax({
type: 'POST',
url: url,
data: data,
success: success,
dataType: dataType
});
, I mean not shorthand Axaj Call. You have options like "success", "error", "completed" and can isolate issue.
I encountered the same error on ASP.NET MVC. On your model, you put ConvertEmptyStringToNull = false on your model's property's attribute:
[DisplayFormat(ConvertEmptyStringToNull = false)]
E.g.
public class Person
{
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Lastname { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Firstname { get; set; }
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string Middlename { get; set; }
}
I documented when I encountered the same thing at this post: http://www.ienablemuch.com/2011/08/empty-string-is-empty-string.html