WCF Service Not Parsing jsonP Parameters correctly - javascript

I'm sending a call like so:
$.ajax({
url: myURL+functionName,
contentType: "application/json; charset=utf-8", //also tried application/javascript
cache: false,
dataType: "jsonp",
data: parameter,
success:function(response){
alert("great success!");
},
error:function(error) {alert("boo-urns");}
Which is fine and everything looks like it should. The parameter object comes in with a value like so:
{ac:"a8d8e6ef-5907-4978-11cf-39add52b996c",
date:"20160626",
deviceId:"W-eXXX9680-13X3-9317-f1b3-eXXXXe50",
komponenten:Array[5],
menu_kf_nr:1,
mz_nr:"3",
pt_kf_nr:1,
pt_nr:"311701",
sessionId:"b22bXXX6-20XX-4XXX-9ed6-0dXXb297"}
Here is the server side method:
public bool functionName(string ac, string date, string deviceId, List<komponenten> komponenten, int? menu_kf_nr, string mz_nr, int pt_kf_nr, string pt_nr, string sessionId) {
//do stuff with the data
}
And then on the server side though my params only come as follows:
ac "a8d8e6ef-5907-4978-11cf-39add52b996c" string
date "20160626" string
deviceId null string
komponenten null System.Collections.Generic.List<kompnenten>
menu_kf_nr null int?
mz_nr "3" string
pt_kf_nr 1 int
pt_nr "311701" string
sessionId null string
Can anyone tell me where I need to look in order to eliminate the nulls?
Thanks in advance

You should pass your parameters individually in the aJax call, also, the C# side is probably expecting JSON data to be received.
Take a look here to see how to pass multiple parameters in an aJax call.
Note the second part of the accepted answer, using JSON.Stringify

Related

JSON Stringify Not Working on Array (ASP.NET)

EDIT2: Found the solution, please see JSON, AJAX, and ASP.NET
The problem ended up being that the parameter in the ajax call is NOT sent to the WebMethod on the server side as a string. The JSON string in the data field of the ajax call is actually converted to the object type specified in the WebMethod's parameter. That being said, my problem was that the data was not being passed into the WebMethod as a string, but a different object type.
EDIT: Looking at the browser console in Chrome, i'm getting this error: Failed to load resource: the server responded with a status of 500 (Internal Server Error). Digging in deeper, I have the following response:
{"Message":"Type \u0027System.Collections.Generic.IDictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]\u0027 is not supported for deserialization of an array.","StackTrace":" at System.Web.Script.Serialization.ObjectConverter.ConvertListToObject(IList list, Type type, JavaScriptSerializer serializer, Boolean throwOnError, IList\u0026 convertedList)\r\n at System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeInternal(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object\u0026 convertedObject)\r\n at System.Web.Script.Serialization.ObjectConverter.ConvertObjectToTypeMain(Object o, Type type, JavaScriptSerializer serializer, Boolean throwOnError, Object\u0026 convertedObject)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize(JavaScriptSerializer serializer, String input, Type type, Int32 depthLimit)\r\n at System.Web.Script.Serialization.JavaScriptSerializer.Deserialize[T](String input)\r\n at System.Web.Script.Services.RestHandler.GetRawParamsFromPostRequest(HttpContext context, JavaScriptSerializer serializer)\r\n at System.Web.Script.Services.RestHandler.GetRawParams(WebServiceMethodData methodData, HttpContext context)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall(HttpContext context, WebServiceMethodData methodData)","ExceptionType":"System.InvalidOperationException"}
The following ajax call is never executed, and it seems like the data parameter does not have a valid value. If data is set equal to a string literal with valid JSON, there is no problem. There just seems to be an issue converting javascript objects into a valid parameter for data in the ajax call. Please see the below code snippet in my aspx file:
<script type="text/javascript">
$(document).ready((function () {
$('#mytable tr').click(function (event) {
var array = [];
$(".tdval").each(function () {
array.push({
value: $(this).html()
});
});
alert(JSON.stringify(array)); //produces what appears to be valid json after calling stringify: [{"value":"val1"},{"value":"val2"}]
$.ajax({
type: "POST",
url: "schedule.aspx/GetCurrentTime",
data: JSON.stringify({ array }), //this seems to be the issue
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response){
alert(response.d + "lol");
},
complete: function () {
alert("complete");
}
});
});
}));
</script>
And this is the method in the C# code behind that the ajax call posts to:
[System.Web.Services.WebMethod]
public static string GetCurrentTime(string name)
{
return "Hello ";
}
Interestingly, I am able to change data: JSON.stringify({ array }) in the ajax call to some random json as a string literal and it works fine as it should. But when using stringify, the "success" callback method from the ajax call is never executed. Any thoughts?
You have the array inside an object when you call JSON.stringify(), so the JSON you're sending will look like:
{ array: [{"value":"val1"},{"value":"val2"}] }
instead of what you alerted earlier in the function.
Instead, use:
data: JSON.stringify(array),

How to receive Non-primitive data in WebMethod?

I am trying to pass an array of bytes to my WebMethod through JavaScript.
The problem is that my WebMethod returns with the message "The test form is only available for primitive methods as parameters."
When I change data type to string or any other kind of primitive variables the WebMethod accepts it goes on.
I'm transforming an object into a byte[], named msgpackEnvio using MessagePack(The transformation itself occurs well), and then sending to WebService.
Here's my request to WebService using jquery
$.ajax({
beforeSend: function (request) {
request.setRequestHeader("Content-Type", "application/json");
},
processData: false,
dataType: "json",
url: url,
data: msgpackEnvio,
type: "POST",
error: function (data) {
$('#upload-load').hide();
$('.bt-enviar-excel').removeAttr('disabled', 'disabled');
var msg = document.getElementsByClassName('msg')[0];
msg.style.color = 'red';
msg.innerHTML = 'Erro interno servidor!';
},
success: //some code
In fact, the code above doesn't matters at all, my problem is in the webService, and how to make it receive an array or perhaps an object.
And here's my WebMethod that should be able to receive a byte[]
[WebMethod]
public string TestMessagePack(byte[] name)
{
//my code
return "Finish";
}
You can use base64 encoding and decoding to send byte arrays as strings. Anything more than that and you might want to use post requests and JSON serialization/deserialization instead. There's not going to be a generic one size fits all conversion between complex C# objects and javascript objects which is why only primitive parameters are allowed, so for nonprimitive things you'll need a translation layer. That's normally going to mean some form of string serialization and deserialization.

AJAX call to server side function in javascript?

I'm new to AJAX and I'm not too clear about how to use the format of the AJAX call
ex
$.ajax({
type: "POST",
url: "Default.aspx/function",
data: '{ searchBy: id }',
contentType: "application/json; charset=utf-8"
}).success(function (result) {
alert(result);
})
I have a function in the .cs file that should take in a string ID and return a list of all the objects that contain that ID.
I want to call this function in the javascript to check that the returned list is null (therefore the ID does not already exist) before inserting new objects into the database.
How could I go about doing this?
All the examples I see return a string from the server side function.
If you have control of the server-side endpoint, then return whatever you want to indicate no matches - an empty list, null, empty string, etc. Then in the success function check for that.
Note the dataType ajax parameter. That tells the ajax function how to format the response for you to consume. If you are expecting JSON to be returned, use dataType: json and in the success function check for an empty json array result.length === 0. In the case of null or empty string, use a dataType: text and check for result == "null" or result == "". Etc.
If you don't have control of server side then you will need to conform to whatever data it sends back to you. The dataType is still the key though.
[WebMethod]
public static int function(int Id)
{
return Id;
}
If you need use only ajax, the best option is XMLHttpRequest, is Vanilla JS and more fast.
If you decide use ajax with jquery the function is:
$.ajax({
type: "POST",
url: "Default.aspx/function",
data: { searchBy: id },
dataType: 'json',
success: function(result) {
// Do something
}
});
I've never done C#, but your url parameter must be a path to a file (e.g. url: Default.aspx). In your file, you should have the logic to handle the request and call the right function. This function will check the DB, and will print the result.
// inside Default.aspx
// 1- is there a POST parameter? If so, call foo()
public static string foo(string postParam) {
// check DB, process
Print(result)
}
Inside your success callback, check if null:
.then(function(result) {
if (result === null) // do stuff
})

Using FormParams with Jersey and jQuery

Seems like this is an infrequently answered questions that's frequently asked. The documentation is somewhat ambiguous.
I want to post a set of parameters as described below.
Web service:
#POST
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public Response post(#FormParam("param") String param){
// code..
}
javascript:
//var paramData = {"startDate":$("#startDate").val()};
var paramData = {startDate:$("#startDate").val()};
$.ajax({
type : 'POST',
url : 'mysite.com/post',
data: paramData,
contentType: 'application/x-www-form-urlencoded',
processData: false,
});
I've changed the contentType to false, tried serializing and stringfying the param data, etc. Either the argument comes in as null in the service or it returns an unsupported media type HTTP error code.
You are doing it wrong...
1. By default, your contentType will be application/x-www-form-urlencoded, so it's not necessary to specify it.
2. Why are you using processData: false? you should read the documentation from here:
http://api.jquery.com/jQuery.ajax/
processData (default: true)
Type: Boolean
By default, data passed in
to the data option as an object (technically, anything other than a
string) will be processed and transformed into a query string, fitting
to the default content-type "application/x-www-form-urlencoded". If
you want to send a DOMDocument, or other non-processed data, set this
option to false.
3. Since processData is true by default and you don't need this to be false then it's not necessary to specify it.
4. You are just passing an Object as the data but where did you specify the param since that's the name that you used for your method? Take a look: public Response post(#FormParam("param") String param)
5. Since your param is a String you will need to convert your Object into a queryString (same as if we were serializing a form) and you can do it easily with jQuery, you should read the following: http://api.jquery.com/jquery.param/
6. So, at the end your code must look like this:
var data = {
name: 'Oscar',
lastname: 'Jara'
};
$.ajax({
type: 'POST',
url: 'rest/service',
data: {
param: $.param(data)
}
});
7. Now, if you print what your param variable contains inside your REST service, you will get this:
name=Oscar&lastname=Jara

How can I get a Spring #RestController to accept parameters in JSON format rather than www-form-urlencoded?

Using Spring 4.1.7 on JDK 1.8, I have an #RestController class that looks like this:
#RestController
public class ServiceAController {
public static final Logger LOG = Logger.getLogger(ServiceAController.class);
#RequestMapping(value="/rest/servicea", method=RequestMethod.POST)
public ServiceAResponse serviceA(#RequestParam(value="parmA", defaultValue="defaultParmA") String parmA,
#RequestParam(value="parmB", defaultValue="defaultParmB") String parmB,
#RequestParam(value="parmC", defaultValue="defaulParmC") String parmC) {
LOG.info("Inside Service A handler: " + parmA + " B: "+ parmB + " C: "+ parmC);
}
When I send a POST to /rest/servicea from a javascript like this, everything works, and I see the values "a", "b", and "c" printed in my log:
var data = {
"parmA": "a",
"parmB": "b",
"parmC": "c"
}
$.ajax({
type: "POST",
url: "./rest/servicea",
contentType: "application/x-www-form-urlencoded",
data: data,
dataType: "json",
success: submitAuthSuccess,
error: submitAuthFailure
})
However, when I try to change the call from the javascript to this (to change the protocol to REST rather than www-urlencode), I get the default values (defaultParmA, defaultParmB, defaultParmC) in my log:
var data = {
"parmA": "a",
"parmB": "b",
"parmC": "c"
}
$.ajax({
type: "POST",
url: "./rest/servicea",
contentType: "application/json",
data: JSON.stringify(data),
dataType: "json",
success: submitAuthSuccess,
error: submitAuthFailure
})
I think I'm missing something in the #RestController class to get it to parse the JSON rather than expecting www-urlencoded data.
I tried changing the #RequestMapping annotation on the serviceA method to add the consumes="application/json" attribute, but that had no effect.
What can I change to make this work, using JSON rather than urlencoded data in the POST body?
The #RequestParam javadoc states
Annotation which indicates that a method parameter should be bound to
a web request parameter.
This is retrieved through the various ServletRequest methods for request parameters. For example, ServletRequest#getParameterMap() which states
Request parameters are extra information sent with the request. For
HTTP servlets, parameters are contained in the query string or posted
form data.
In your second snippet, you aren't sending either. You're sending JSON in the request body.
Spring has a mechanism (it has many, and custom ones) for deserializing that into the data you expect. The standard solution is #RequestBody, assuming you have an appropriately registered HttpMessageConverter that can handle the JSON. Spring automatically registers MappingJackson2HttpMessageConverter if you have Jackson 2 on the classpath, which can correctly deserialize JSON into Java POJO types.
The documentation gives a number of examples and explains how you would use it. With JSON, you could define a POJO type with fields that correspond to the ones you send
class RequestPojo {
private String paramA;
private String paramB;
private String paramC;
// and corresponding getters and setters
}
and add a #RequestBody annotated parameter of this type to your handler method
public ServiceAResponse serviceA(#RequestBody RequestPojo pojo) {
pojo.getParamB(); // do something
return ...;
}
Jackson lets you define, through annotations or through configuration of the ObjectMapper, how to deal with absent values.
#RestController is not involved here. As its javadoc states,
Types that carry this annotation are treated as controllers where
#RequestMapping methods assume #ResponseBody semantics by default.
It looks to me like you are passing a single JSON object at this point, rather than a set of parameters, hence Spring cannot match what you're sending to any of the parameters you've provided.
Try
#RequestBody List<ListUnit> listOfUnits
instead of #RequestParam

Categories