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),
Related
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.
Below is the code which i m trying to send. As you can see, ajax call is made at UI and data 'sub' is passed through. this 'sub' has an array of objects in it. So data is present when it is passed.
UI SIDE
$scope.save = function () {
var sanit = $scope.gridOptions.rowData;
var sub = JSON.stringify(sanit);
$.ajax({
type: 'POST',
url: '/api/Pr/PM',
data: sub, //this has data in it
contentType: "application/json"
}).success(function (response) {
window.alert("Database updated successfully.");
})
};
However, when i debug the code at backend, the parameters is showing as null. i have commented the section showing this is null where the data is showing as null at the start of backend function.
BACKEND C# SIDE
[HttpPost]
public HttpResponseMessage PM([FromBody] string parameters) //this is null.
{
string message = string.Empty;
try
{
var model = JsonConvert.DeserializeObject<List<PODetails>>(parameters);
message = "Insert Successfull";
return Request.CreateResponse(HttpStatusCode.OK, message);
}
catch (Exception ex)
{
message = "Insert fail";
return Request.CreateErrorResponse(HttpStatusCode.NoContent, message);
}
}
Can someone please let me know why it is showing as null value at backend.
You need to ensure the data you're sending via AJAX is an object with a single parameter, which should be named the exact same as the parameter your backend is expecting.
In this case:
$.ajax({
type: 'POST',
url: '/api',
data: JSON.stringify({ parameters: sub }),
contentType: "application/json"
}).success(function (response) {
...
})
Next, if the variable "sub" is an array of objects then you must create a class model server side to match the structure of the data being sent. Then, your API's interface should be expecting a list of that newly created class.
For example:
[HttpPost]
public HttpResponseMessage PM(List<YourClassModel> parameters)
{
...
}
Your API should now be able to receive and read the data being sent via the AJAX call above.
Take a look at this: Post a json object to mvc controller with jquery and ajax
You are sending a list of objects but trying to recieve it as string. You should change your function parameter from (String parameters) to (List parameters) and change your ajax request according to the link above. That will probably solve your problem.
(ps: i couldn't try it myself that's why i said probably :) )
I have a serialized string comming from the controller to a view:
Controller:
var serialize = new JavaScriptSerializer();
return Json(new
{
data = serialize.Serialize(obj)
}, JsonRequestBehavior.AllowGet);
Json string:
[{"indiceName":"Caracter","indiciId":24,"indiceId":1,"tamanhoIndice":10,"mask":null,"indiceObr":1},
{"indiceName":"Numérico","indiciId":25,"indiceId":2,"tamanhoIndice":10,"mask":null,"indiceObr":0},
{"indiceName":"AlfaNumérico","indiciId":26,"indiceId":3,"tamanhoIndice":10,"mask":null,"indiceObr":0}]
As far as I know, modern browser should be able to parse that string with a simple
Json.parse()
View:
success: function (data)
{
$('.dinamic').remove();
console.log(data);
var obj2 = JSON.parse(data);
console.log(obj2);
}
I am able to see that string in the first console.log, but I get nothing from the second.
Is there any thing else I should be looking at because all the post I have read people only do it as simple as it is with a single JSON.parse.
I am using latest version of google chrome ,firefox and IE so it should work.
Although your success function is not shown in context of the other AJAX options being given, I would guess you are passing a dataType option of "json", or are using $.getJSON or something similar.
If that is the case, jQuery has already parsed the JSON for you by the time it passes it into success so you do not need to (and cannot) parse it again. You can simply use your data structure (data[0]. indiceName and etc).
(The below code is running live at http://jaaulde.com/test_bed/GuilhermeLongo/ )
Consider the following PHP (stored in json.php):
<?php
exit('[{"indiceName":"Caracter","indiciId":24,"indiceId":1,"tamanhoIndice":10,"mask":null,"indiceObr":1},{"indiceName":"Numérico","indiciId":25,"indiceId":2,"tamanhoIndice":10,"mask":null,"indiceObr":0},{"indiceName":"AlfaNumérico","indiciId":26,"indiceId":3,"tamanhoIndice":10,"mask":null,"indiceObr":0}]');
And the following JS:
<script src="http://code.jquery.com/jquery.min.js"></script>
<script>
$.ajax({
url: 'json.php',
type: 'get',
dataType: 'json',
success: function (data) {
console.log(data[0]);
console.log(data[0].indiceName);
},
error: function () {
throw new Error('AJAX request error occurred.');
}
});
</script>
It results in the following outputted log info:
GET http://jaaulde.com/test_bed/GuilhermeLongo/json.php
200 OK
99ms
jquery.min.js (line 3)
Object
{indiceName="Caracter", indiciId=24, indiceId=1, more...}/test_...eLongo/
(line 8)
Caracter
I get the following error "Web Service method name is not valid" when i try to call webmethod from javascript
System.InvalidOperationException: SaveBOAT Web Service method name is not valid.
at System.Web.Services.Protocols.HttpServerProtocol.Initialize()
at System.Web.Services.Protocols.ServerProtocol.SetContext(Type type, HttpContext context, HttpRequest request, HttpResponse response)
at System.Web.Services.Protocols.ServerProtocolFactory.Create(Type type, HttpContext context, HttpRequest request, HttpResponse response, Boolean& abortProcessing)
HTML Code :
<asp:LinkButton runat="server" ID="lnkAddBoat" OnClientClick="javascript:AddMyBoat(); return false;"></asp:LinkButton>
JS Code :
function AddMyBoat() {
var b = document.getElementById('HdnControlId').value;
jQuery.ajax({
type: "GET",
url: "/AllService.asmx/SaveBOAT",
data: { Pid: b },
contentType: "application/text",
dataType: "text",
success: function(dd) {
alert('Success' + dd);
},
error: function(dd) {
alert('There is error' + dd.responseText);
}
});
}
C# Code (Web method in AllService.asmx file)
[WebMethod]
public static string SaveBOAT(int Pid)
{
// My Code is here
//I can put anythng here
SessionManager.MemberID = Pid;
return "";
}
I tried all solutions found on Stack Overflow and ASP.NET site.but none of them worked for me.
It was a silly mistake.
remove Static keyword from method declaration.
[WebMethod]
public string SaveBOAT(string Pid)
{
SessionManager.MemberID = Pid;
return "";
}
In my case I had copied another asmx file, but not changed the class property to the name of the new class in the asmx file itself (Right click on asmx file -> View Markup)
In my case the error was that the Web Service method was declared "private" instead of "public"
Try using this, I think datatype should be JSON
jQuery.ajax({
type: "POST", // or GET
url: "/AllService.asmx/SaveBOAT",
data: { Pid: b },
contentType: "application/json; charset=utf-8",
dataType: "json"
success: function(dd) {
alert('Success' + dd);
},
error: function(dd) {
alert('There is error' + dd.responseText);
}
});
And in C# Code change Pid to string
[WebMethod]
public static string SaveBOAT(string Pid)
{
SessionManager.MemberID = Pid;
return "";
}
I too faced the similar issue. The solution includes checking everything related to ensuring all name, parameters are passed correctly as many have responded. Make sure that the web method name that we are calling in UI page is spelled correctly, the data, data types are correct and etc. In my case, I misspelled the web method name in my ajax call. It works fine once I found and corrected the name correctly.
For Ex: In .asmx class file, this is the method name "IsLeaseMentorExistWithTheSameName" but when I called from UI this is how I called:
var varURL = <%=Page.ResolveUrl("~/Main/BuildCriteria.asmx") %> + '/IsLeaseMentorExistWithSameName';
Notice that the word "The" is missing. That was a mistake and I corrected and so it worked fine.
As Sundar Rajan states, check the parameters are also correct. My instance of this error was because I had failed to pass any parameters (as a body in a POST request) and the asmx web method was expecting a named parameter, because of this the binding logic failed to match up the request to the method name, even though the name itself is actually correct.
[WebMethod]
public object MyWebMethod(object parameter)
If there is no parameter in the body of the request then you will get this error.
Did U add ServiceReference Class. Check this once. Based on your comment I can tell what to do
I had this issue because my soap method had a List<string> parameter. Couldn't figure out a way to make it work with the array parameter; so just converted the parameter to a &-delimited string (e.g. val1&val2&val3) and converted the parameter to an array in the service method.
In my case, one of the WebService receiving parameters was called aId. When I called it from javascript, I was sending the correct Id value, but the name of the sent variable was incorrectly called bId. So I just had to rename the WebService call, keep the correct value like before, and just change the variable name.
I'm attempting to call a web service via AJAX in a WebForms application.
My script looks something like this:
$.post('UpdateServer.asmx/ProcessItem',
'itemId=' + $(this).text(),
function (result) {
alert(result);
});
My web service looks something like this.
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class UpdateServer : System.Web.Services.WebService
{
[WebMethod]
public string ProcessItem(int itemId)
{
return new JavaScriptSerializer().Serialize(
new { Success = true, Message = "Here I am!" });
}
}
The web method is called as expected and with the expected argument. However, the argument passed to my success function (last parameter to $.post()) is of type document and does not contain the Success and Message members that I'm expecting.
What's are the magic words so that I can get back the object I'm expecting?
EDIT
On closer inspection, I can find the data I'm looking for as follows:
result.childNodes[0].childNodes[0].data:
"{"Success":true,"Message":"Server successfully updated!"}"
The reason you're seeing that odd structure of nodes that end with JSON is because you're not calling the service the necessary way to coax JSON out of ASMX ScriptServices and then returning a JSON string anyway. So, the end result is that you're returning an XML document that contains a single value of that JSON string.
The two specific problems you're running into right now are that you're manually JSON serializing your return value and you're not calling the service with a Content-Type of application/json (.NET needs that to switch to JSON serializing the response).
Once you fixed those issues, you'd also run into an "invalid JSON primitive" error due to the data parameter being URL encoded instead of a valid JSON string.
To get it working, do this on the server-side:
[ScriptService]
public class UpdateServer : System.Web.Services.WebService
{
[WebMethod]
public object ProcessItem(int itemId)
{
return new { Success = true, Message = "Here I am!" };
}
}
You could also create a data transfer object (aka ViewModel) to return instead of using an anonymous type and object, if you want.
To successfully get raw JSON out of that, do this on the client-side:
$.ajax({
url: 'UpdateServer.asmx/ProcessItem',
type: 'post',
contentType: 'application/json',
data: '{"itemId":' + $(this).text() + '}',
success: function(result) {
// This will be { d: { Success: true, Message: "Here I am!" } }.
console.log(result);
}
});
If you have a few minutes, read through the posts in the communication section of jQuery for the ASP.NET developer. You'll find a lot of that information helpful as you continue down this path.
Note: The links that helmus left were relevant. Nothing has fundamentally changed between 2.0 and present with regards to using ASMX ScriptServices to communicate via JSON. If you're interested in the truly cutting edge approach to this problem in .NET, ASP.NET Web API is the way to go.
Add this attribute to your ProcessItem method:
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
Be more explicit in your $.post call.
$.ajax({
type:'post',
url:'UpdateServer.asmx/ProcessItem',
data: {'itemId':$(this).text()}
}).done(function (result) {
alert(result);
});