Sending a complex object as parameter to Asp.Net PageMethod - asp.net

I am trying to send an object created in JavaScript to an ASP.NET PageMethod. This object mirrors the properties of an existing custom business object, so i was hoping that i could pass a single object instead of a parameter for each property. I am getting an error "Unknown web method SavePart when attempting to use this method.
Javascript:
function() {
var pt = { Id: 1, Onhand: 20, LowPoint: 30, __type: 'Custom.Objects.Part'};
$.ajax({
type: 'POST',
url: 'partlist.aspx/SavePart',
data: JSON.stringify(pt),
contentType: 'application/json; charset: utf-8;'
dataType: 'json',
success: function(results) { alert('Success!'); }
});
}
Code Behind:
<WebMethod()> _
Public Shared Function SavePart(pt as Custom.Objects.Part) as Boolean
Dim repo as new PartRepository()
return repo.Save(pt)
End Function
I am using another PageMethod which just accepts an int, and this works fine.

I ended up solving my problem by sending the object this way through the jQuery ajax command:
data: '{"pt":' + JSON.stringify(pt) + '}'
this serialized the object automatically and returned it to my WebMethod. When i tried sending the object as is, i got an error saying "invalid JSON primitive".

You are attempting to pass a string to the method. You will need to accept the string, and deserialize it with fx. JavascriptSerializer or JSON.NET

I know this is incredibly old, but its not very intuitive when you're using this to figure out what the issues are. You are very close but I wanted to add a bit more to this in case someone else later wants to do the same thing. This works with nested objects as well, the one thing I can say is CASE matters in your JS variables that map to .NET POCOs on the page method.
Your "answer" is where I will start with. And as in the comments below it, yes you have to pass the object wrapped in its page method variable name.
Ill say it again, this is CASE-Sensitive, and can trip you up not just on the object's name but its properties as well. So to combat this I usually create my POCO object in .NET then copy that to the page so I know the names, capitalization and all are correct.
Something like this:
POCO:
Public Class CustomObject
Public Property Id as integer
Public Property ReqDate as DateTime
Public Property Message as string
End Sub
Now with a defined POCO for page method, replicate that "model" exactly as it is for the JS/AJAX to post with, being vigilant about case-sensitivity.
function ParseAndPostData()
{
var data = { custobj: {
Id: 1,
ReqDate: "04/12/2018",
Message:"Hello!"
}
};
//Stringify the data so it goes through page method parser
var postdata = JSON.stringify(data);
$.ajax({
type: 'POST',
url: '/BasePath/SomePage.aspx/SomeMethod',
data: postdata,
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (msg) {
var parsedACData = JSON.parse(msg.d);
alert(parsedACData);
},
error: function (msg) {
alert(msg);
}
});
}
Page Method (Note custobj in the parameters):
<WebMethod()> _
Public Shared Function PostCustomObject(custobj as CustomObject) as String
return custobj.Message
End Function

Related

Getting data from database in a webmethod return null in vb.net

I am trying to get data from a stored procedure in a webmethod inside an asmx service but whatever I try it returns null.
<WebMethod()>
<ScriptMethod(ResponseFormat:=ResponseFormat.Json, UseHttpGet:=False,
XmlSerializeString:=False)>
Public Function SendIdDocuments(ByVal idReferto As String)
'This id has been sent from ajax as json and now I am converting it to string
'in order to use it as parameter in stored procedure.
Dim idRef As String = JsonConvert.DeserializeObject(idReferto)
Dim dtRefertoDocIndex As DataTable = operations.G_REPORT_BY_ID(idRef)
Dim version As String = dtRefertoDocIndex.Rows(0)("VERSION")
MsgBox(Cstr(version))
End If
I have tried these:
1) Dim dtRefertoDocIndex As DataTable = operations.G_REPORT_BY_ID(Cstr(idRef))
2) Dim dtRefertoDocIndex As DataTable = operations.G_REPORT_BY_ID(idRef.ToString)
These dont work too. I have checked the idRef that has a value and also data from database isn't returning null and version has a value, but in the code dtRefertoDocIndex is null and for this reason version comes as null too. Any help would be appriciated.
A few things. Obviously you can't really use msgbox.
Next up, .net should return JSON without you having to specify it, but we can leave that.
Your web method WILL automatic split out the parameters for you.
So, your web method ALSO needs to be a function that RETURNS a value, say a string
thus it should be:
<WebMethod()>
Public Function SendIdDocuments(ByVal idReferto As String) as string
Dim dtRefertoDocIndex As DataTable = operations.G_REPORT_BY_ID(idRef)
Dim strResult as string = dtRefertoDocIndex.Rows(0)("VERSION")
return strResult
End If
Note this part: Public function bla bla bla) as string <---- your function HAS to return something, right?
Now WHY did I create a string to hold the return value and THEN return it?
Answer:
Because I do NOT want to take a chance that the return type is a column cell, or ANY OTHER data type OTHER then a string. So, to be 100%, 200%, 300% of the correct data type being returned? I create a nice separate string, and stuff the value into that string, and THEN return that SIMPLE string type. This removes ANY doubt that we ARE in fact returning a simple string type. When we execute the return strResult?
It will be converted back into a json result.
Ok, now, lets setup the JavaScript (client side) ajax call.
jQuery:
function GetDocByID() {
var MyDocID = 123;
$.ajax({
type: "POST",
url: 'WebService1.asmx/MakeName',
data: JSON.stringify({idReferto: MyDocID}),
contentType: "application/json; charset=utf-8",
datatype: "json",
success: function (em) {
alert('VERSION result = ' + em.d);
}
});
}
If you not using jQuery, then of course you have to re-write above.
So, .net will automatic convert to and from json for you. And ALSO VERY careful note how the parameter name in JavaScript (jQuery) MUST match the parameters in the public function you created.
Here is another simple example. We pass firstname, last name, and return the two as a single string:
<WebMethod()>
Public Function MakeName(FirstName As String, LastName As String) As String
Dim strResult As String = ""
strResult = FirstName & " " & LastName
Return strResult
End Function
and the js/jQuery is:
function GetNameTest() {
var MyFirstName = 'Albert';
var MyLastName = 'Kallal';
$.ajax({
type: "POST",
url: 'WebService1.asmx/MakeName',
data: JSON.stringify({ FirstName: MyFirstName, LastName: MyLastName }),
contentType: "application/json; charset=utf-8",
datatype: "json",
success: function (em) {
alert('name result = ' + em.d);
}
});
}
Note again HOW we used the actual vb.net FirstName and LastName DEFINED in the public function.
Note again: the function has a return value (string).
And if you look at the web service template, note that you WANT to un-comment the FIRST line as outlined like this:
' To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
<System.Web.Script.Services.ScriptService()>

ASP.NET - WebMethod not getting called when using Class, jsonerror

I am trying to pass an object to a WebMethod which takes parameters as a class.
If I pass the parameters separately, it works, but not as a class. What am I missing?
My ajax call:
var obj = {Id: 1234};
var item = JSON.stringify(obj);
$.ajax({
url: 'InventoryItems.aspx/Update',
data: item,
type: 'POST',
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function () {
console.log("in success");
}
})
WebMethod:
The version that works:
<WebMethod(EnableSession:=True)>
Public Shared Function Update(Id As string) As String
Dim res As String = ""
Return res
End Function
WebMethod:
The version that does not work:
<WebMethod(EnableSession:=True)>
Public Shared Function Update(item As Item) As String
Dim res As String = ""
Return res
End Function
The class Item:
Public Class Item
Public Property Id As String = String.Empty
End Class
I get a 500 error in Google Chrome dev tool. So, in gist, the WebMethod does not get hit if I put a breakpoint there. If I use just the Id as the parameter in the WebMethod, it gets hit. My original object has about 20 properties, so I would like to pass an object with 20 fields rather than passing 20 parameters separately.
Am I missing anything? Any reference or settings?
Thank you for helping me in advance.
The problem on my end is FriendlyUrls.
There's probably a better way to do this, but I excluded it from the project in the bin folder; and commented-out references to it in RouteConfig.cs and ViewSwitcher.ascx. (You may have others.)
This was just for testing, but the problems I was having are gone on this page. I also have a script manager on my test-page, and the script manager and bundling are commented-out on the master page, but now I'm not convinced that that's an issue.
I guess the ASP.NET AJAX proxy class PageMethods looks for a complete url to find the code-behind method and bombs without it.
When you are using input parameter as integer, its working fine as your JSON is compliant with the parameter
For parameter as an object, use following
{ "item": { "Id": "1234" } }
If the underlying Id property is a number, remove the corresponding quotes on 1234.
Note that the parameter name are case sensitive and hence "item" should have i in lower case and "Id" has in upper case.
You follow the convention of :-
Opening and closing braces marks the boundary of field
Variable name has to be 1st ('item' in this case)
Variable value follows after a colon (an object with property "Id' and its corresponding value
2) & 3) gets repeated for the whole hierarchy of the concerned object.
The following worked for me:
The ajax call:
var obj = {Id: 1234};
var item = JSON.stringify(obj);
$.ajax({
url: 'InventoryItems.aspx/Update',
data: JSON.stringify({item:item}),
type: 'POST',
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function () {
console.log("in success");
}
})
<WebMethod(EnableSession:=True)>
Public Shared Function Update(item As string) As String
Dim res As String = ""
Return res
End Function
And then in that WebMethod, I could do something like:
Dim jss As New JavaScriptSerializer()
Dim itemDetails As Item = jss.Deserialize(Of Item)(item)
dim id as string = itemDetails.Id

Action page in asp.net

How do i create a page like an action page in php, in C# ?To be specific I only require a page that contains only methods that handle various operations and return result.
How do i solve the above scenario ?
Create a class, then inside the class create your methods to construct the logic behind your application.
Then reference this class with the using keyword in your web pages and use the methods you created wherever you like.
Read about HttpHandlers.
For example, you want to have a method that returns a json string in a web forms application.
Add a new item to your project of type "Generic Handler". This will create a new .ashx file. The main method of any class that implements IHttpHandler is ProcessRequest.
public void ProcessRequest (HttpContext context) {
if(String.IsNullOrEmpty(context.Request["day"]))
{
context.Response.End();
}
string json = "";
byte[] bytes = getByteArray();
json = JsonConvert.SerializeObject(bytes);
context.Response.ContentType = "text/json";
context.Response.Write(json);
}
Change the url in your AJAX call and that should do it. The JavaScript would look like this , where GetFileHandler.ashx is the name of the IHttpHandler you just created:
$.ajax(
{
type: "POST",
async: true,
url: 'Handlers/GetFileHandler.ashx',
data: "Day=" + $.toJSON(day),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
console.log("SUCCESS:" + msg);
},
error: function (msg) {
console.log("error:" + msg);
}
});
Read more here for more details.

How to call non static method from AJAX?

Here is my code behind I am calling from AJAX...
[WebMethod]
[ScriptMethod]
public static string save(string parameter)
{
country_master obj_country = new country_master();
obj_country.Country_Name = Page.Request.Params["name"].ToString().Trim();
obj_country.saved();
return "";
}
Here I am not able to access parameters passed from the page via Page.Request.
string name = HttpContext.Current.Request.QueryString["name"].Trim();
return "error";
after writing the first line, return statement does not return anything to the AJAX.
Please Help me how to do that.
Thanks...
To get the current context you can use HttpContext.Current, which is a static property.
Once you have that you can access things like session or profile and get information about the state of the site
HttpContext.Current.Session etc..
This link may help you : Call Server Side via AJAX without a Static Method
The reason behind restricting the web method to be static is to avoid it access the controls of the instance page.
Yo could use the HttpContext.Current static class, however you can skip that if you declare on your method the parameters you want to use and just pass the parameters with your AJAX call
You should pass parameters directly to the method.
I have several working examples on my Github repository, feel free to browse the code.
As a summary, to call a PageMethod:
Note: how using AJAX the jobID PageMethod parameter is being passed along with the request and how is used inside the PageMethod transparently
AJAX call
$.ajax({
type: 'POST',
url: '<%: this.ResolveClientUrl("~/Topics/JQuery/Ajax/PageMethods_JQueryAJAX.aspx/GetEmployees") %>',
contentType: 'application/json; charset=utf-8',
dataType: 'json',
data: '{"jobID" : ' + jobID +'}',
async: false,
cache: false,
success: function (data) {
$('#employees').find('option').remove();
$.each(data.d, function (i, item) {
$('<option />').val(item.EmployeeID).text(item.FirstName).appendTo('#employees');
});
},
error: function (xhr) {
alert(xhr.responseText);
}
});
Page Method
[WebMethod]
public static List<EmployeeModel> GetEmployees(int jobID)
{
var ctx = new PubsDataContext();
return (from e in ctx.employee
where e.job_id == jobID
orderby e.fname
select new EmployeeModel
{
EmployeeID = e.emp_id,
FirstName = e.fname
}).ToList();
}

Response.Write() in WebService

I want to return JSON data back to the client, in my web service method. One way is to create SoapExtension and use it as attribute on my web method, etc. Another way is to simply add [ScriptService] attribute to the web service, and let .NET framework return the result as {"d": "something"} JSON, back to the user (d here being something out of my control). However, I want to return something like:
{"message": "action was successful!"}
The simplest approach could be writing a web method like:
[WebMethod]
public static void StopSite(int siteId)
{
HttpResponse response = HttpContext.Current.Response;
try
{
// Doing something here
response.Write("{{\"message\": \"action was successful!\"}}");
}
catch (Exception ex)
{
response.StatusCode = 500;
response.Write("{{\"message\": \"action failed!\"}}");
}
}
This way, what I'll get at client is:
{ "message": "action was successful!"} { "d": null}
Which means that ASP.NET is appending its success result to my JSON result. If on the other hand I flush the response after writing the success message, (like response.Flush();), the exception happens that says:
Server cannot clear headers after HTTP headers have been sent.
So, what to do to just get my JSON result, without changing the approach?
This works for me:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public void ReturnExactValueFromWebMethod(string AuthCode)
{
string r = "return my exact response without ASP.NET added junk";
HttpContext.Current.Response.BufferOutput = true;
HttpContext.Current.Response.Write(r);
HttpContext.Current.Response.Flush();
}
Why don't you return an object and then in your client you can call as response.d?
I don't know how you are calling your Web Service but I made an example making some assumptions:
I made this example using jquery ajax
function Test(a) {
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "TestRW.asmx/HelloWorld",
data: "{'id':" + a + "}",
dataType: "json",
success: function (response) {
alert(JSON.stringify(response.d));
}
});
}
And your code could be like this (you need to allow the web service to be called from script first: '[System.Web.Script.Services.ScriptService]'):
[WebMethod]
public object HelloWorld(int id)
{
Dictionary<string, string> dic = new Dictionary<string, string>();
dic.Add("message","success");
return dic;
}
In this example I used dictionary but you could use any object with a field "message" for example.
I'm sorry if I missunderstood what you meant but I don't really understand why you want to do a 'response.write' thing.
Hope I've helped at least. :)

Resources