I created an ASMX file with a code behind file. It's working fine, but it is outputting XML.
However, I need it to output JSON. The ResponseFormat configuration doesn't seem to work. My code-behind is:
[System.Web.Script.Services.ScriptService]
public class _default : System.Web.Services.WebService {
[WebMethod]
[ScriptMethod(UseHttpGet = true,ResponseFormat = ResponseFormat.Json)]
public string[] UserDetails()
{
return new string[] { "abc", "def" };
}
}
To receive a pure JSON string, without it being wrapped into an XML, you have to write the JSON string directly to the HttpResponse and change the WebMethod return type to void.
[System.Web.Script.Services.ScriptService]
public class WebServiceClass : System.Web.Services.WebService {
[WebMethod]
public void WebMethodName()
{
HttpContext.Current.Response.Write("{property: value}");
}
}
From WebService returns XML even when ResponseFormat set to JSON:
Make sure that the request is a POST request, not a GET. Scott Guthrie has a post explaining why.
Though it's written specifically for jQuery, this may also be useful to you:
Using jQuery to Consume ASP.NET JSON Web Services
This is probably old news by now, but the magic seems to be:
[ScriptService] attribute on web service class
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)] on method
Content-type: application/json in request
With those pieces in place, a GET request is successful.
For a HTTP POST
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)] on method
and on the client side (assuming your webmethod is called MethodName, and it takes a single parameter called searchString):
$.ajax({
url: "MyWebService.asmx/MethodName",
type: "POST",
contentType: "application/json",
data: JSON.stringify({ searchString: q }),
success: function (response) {
},
error: function (jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + jqXHR.responseText);
}
});
A quick gotcha that I learned the hard way (basically spending 4 hours on Google), you can use PageMethods in your ASPX file to return JSON (with the [ScriptMethod()] marker) for a static method, however if you decide to move your static methods to an asmx file, it cannot be a static method.
Also, you need to tell the web service Content-Type: application/json in order to get JSON back from the call (I'm using jQuery and the 3 Mistakes To Avoid When Using jQuery article was very enlightening - its from the same website mentioned in another answer here).
Are you calling the web service from client script or on the server side?
You may find sending a content type header to the server will help, e.g.
'application/json; charset=utf-8'
On the client side, I use prototype client side library and there is a contentType parameter when making an Ajax call where you can specify this. I think jQuery has a getJSON method.
Alternative: Use a generic HTTP handler (.ashx) and use your favorite json library to manually serialize and deserialize your JSON.
I've found that complete control over the handling of a request and generating a response beats anything else .NET offers for simple, RESTful web services.
Related
my stuff works fine with Fiddler and I get desired result. But when i do it on web page thru JQuery AJAx, it says "Not Found". I am struggling since sometime but couldn't get around.
My Controller method is like this
[Route("AddDonors/")]
[HttpPost]
public dynamic addDonors(localDonor localDonor)
{
return localDonor;
}
This is how i am calling from web page
var userInput = { 'FullName': 'Lakshman', 'Mobile': '9924210053' };
$.ajax({
type: "POST",
url: "/AddDonors",
data: userInput,
error: function (result) {
alert(result);
},
datatype: "json"
});
this is the model class
public class localDonor
{
public String FullName { get; set; }
public String Mobile { get; set; }
}
API registering and other settings are just fine since this works in fiddler.
Please help. Thanks.
I strongly suspect that the url in your AJAX request is to blame (404 - Not Found) the request can't be routed to a controller for processing.
Without knowing what your full controller looks like and if you have a RoutePrefixAttribute on this specific controller I can't say what the url should be.
I would suggest you monitor network traffic in your browser developer tools (press F12) and compare the request url for your failing POST request to those of your successful requests in Fiddler
If your webpage is created in ASP.Net MVC as part of the same web project you may want to generate the url server side in future see Construct url in view for Web Api with attribute routing. The #Url helper is only available within your .cshtml files though so you will not be able you shift your JavaScript code to a separate .js file.
i was able to solve the issue by changing the url to url: "AddDonors",
Try to put [WebMethod] attribute.
[Route("AddDonors/")]
[HttpPost]
[WebMethod]
public dynamic addDonors(localDonor localDonor)
{
return localDonor;
}
Hope this works!
Try this for your POST data
var userInput = JSON.stringify({ 'FullName': 'Lakshman', 'Mobile': '9924210053' }),
I had the same error.
As you are using ASP.NET, try making all AJAX calls using the #Url.Action helper.I don't know why, but in some situations in ASP.NET passing the URL as a String doesn't work.And try passing your data like the code belowYour modified code should look something like this:
$.ajax({
type: "POST",
url: "#Url.Action("AddDonors", "ControllerName")",
data: { localDonor: userInput },
error: function (result) {
alert(result);
},
datatype: "json"
});
I have a class in my c# project. Let's say Sample.cs
I want to call it's method using ajax, but don't know how to use class name in url of ajax, I am doing like this, but it's not working
$.ajax({
type: "POST",
url: "Sample.cs/MethodName",
data: '{Id: "' + Id + '"}',
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (response) {
}
});
Please Help Guys...
If you directly want to call a method of a class, you cannot.
You can only make HTTP requests calls.
If you are using, MVC, what you can do is that create an Action method with return type as JsonResult, (as from you snippet, it looks you are expecting json response) call your method from this action method and return the same. Or you can create WebApi services and call that method within the ApiController method.
You can also create a WCF Rest service and call it from your js.
You create a method in an interface in C# which will react to your Http request
Here's an example
[OperationContract]
[WebInvoke(Method = "GET", //React on GET method
ResponseFormat = WebMessageFormat.Json, //Return Json format
BodyStyle = WebMessageBodyStyle.Wrapped, //Wrap request and response
UriTemplate = "login/{id}/{mdp}")] //Template Uri
bool Login(string id, string mdp);
This method will be called if you receive a GET method on an url like
SERVER_NAME/login/myId/myPassword
Note : all your parameters must be of type string
If you don't know what is a REST service here's some links
Wikipedia
If you want to learn how to create a REST webService in C# :
codeProject
Sadly I don't have enough point to post more link...
Hope it helped !
I have been playing with jstree (1.0rc2)+jquery (1.4.2) for the first time with c#.net and although I have gotten it working, there are a couple things that I don't understand about how data is provided to the tree by the webservice I use to populate the tree (using ajax and the json_data plug-in). I was hoping someone with more experience using jstree could provide some insight.
The jstree config looks like this:
"json_data": {
"ajax": {
"url": "GetTree.asmx/GetChildren",
"type": "POST",
"contentType": "application/json; charset=utf-8",
"dataType": "json",
"data": function(n) {
var result = "{'id':'" + (n.attr ? n.attr("id").replace("node_", "") : "0") + "'}";
return (result);
}
}
}
GetTree.asmx GetChildren method:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Xml )]
public string GetChildren(string id)
{
List<jsTreeNode> jsTree = new List<jsTreeNode>();
//... (build the tree as needed)
JavaScriptSerializer serializer = new JavaScriptSerializer();
return(serializer.Serialize(jsTree));
}
Question 1: So everything works great, so what's the problem? The problem is "ResponseFormat = ResponseFormat.Xml". I struggled for a while to get this working because it did not work when it was set to ResponseFormat.Json, which is what I would expect it to be. In that situation, no errors would be reported by the web service or by jQuery when parsing the json response, but the tree would render empty.
In looking at the HTML output of the web service, I could see no difference between what was rendered either way. I was hoping someone could explain why this works (counterintuitively) and why it does not work with ResponseFormat.Json, and if this is indicative of something else I might be doing wrong.
Question 2: Generally, web service or web handler?
Would using a generic web handler (ashx) be a more efficient way to do this anyway? Is there a substantial difference in the overhead required of a standard web service versus a generic web handler? Since my goal is basically to control exactly what is output (and using the json data format in the web service doesn't seem to be working the way I want it to anyway) I am not sure what benefit, if any, there is to using a web service here instead of just stripping it down completely. On the other hand this works now so maybe I should leave well enough alone.
Seeing as this question has almost 600 views and no answers I thought I would answer it myself (since I've long since figured it out).
Using a ScriptMethod is really not the right way to communicate with jQuery ajax. While it can be done, you will notice what I was doing above is returning a string with data that I encoded myself to JSON using JavascriptSerializer.
However, using a ScriptMethod automatically incorporates serialization/deserialization designed to communicate with Microsoft's AJAX framework. Since serializing a pure string with no object wrapper will genererally result in the same string (whether I be returning XML or JSON format), it basically worked, but what was really happening internally is it was being serialized twice.
So what I should have done, at a minimum, was:
public List<jsTreeNode> GetChildren(string id)
that is, the return type should be the actual data type, not a string of serialized data.
However, this still wouldn't be exactly right, because Microsoft's methods wrap the return value in an object d. I could still extract that in Javascript to get the inner data. But if something like jsTree is expecting data in a predefined format this may not be workable.
The best solution is do not use WebServices, use generic handlers (ashx) instead. This gives you complete control over the format and handling of your input and output. It may take a little bit of doing to set yourself up a nice framework, but the frustration of being unable to skip parts of the WebService handling that you don't need makes it well worth it.
Sorry, I have to disagree with your answer the 3.5 framework has really good support for Json serialization and Web Services (and for 2.0 you can use Newtonsoft.Json). Please see my JsTree ASP.NET Web Control Demo at http://code.zyky.com/jsTreeView/Default.aspx and http://asp-net-elephant.blogspot.com/2012/01/how-to-use-jstree-in-aspnet-web-forms.html for an example of both. Hope this helps.
Regarding Question 1 (I cannot speak to Q2), I have gotten a web service to feed JSON back to the jsTree plugin. While I recognize that WCF and REST are more current approaches, and no doubt better in the long run, we still use asmx web services and they do get the job done. But it was not easy: I spent a while trying to get the exact syntax to work in JS so that jsTree would get its data object from an ASP.NET web service. As the OP alludes to in his solution, the problem isn't so much my JS and wiring of the plugin but was with the wonky JSON data that was returned my web service. It -looked- like JSON but it was a string representation of a simplified JSON object.
To fix it I had to deserialize and serialize my json string (I got a clue about this from https://stackoverflow.com/a/20080495/1129926) and the resulting object was consumed happily by jsTree. Here's my web service:
Imports System.Web.Script.Serialization
Public Function GetJsonData() As String
Dim jss As JavaScriptSerializer = New JavaScriptSerializer
' IMPORTANT: do not use single quotes ' in JSON string, use ""
Dim jsonData As String = "" & _
"{ ""text"": ""CONTACTS"", ""children"": [ { ""text"": ""CUSTOMER"", ""column"": ""CLASS"", ""children"": [ { ""text"": ""Excelo Communications"", ""column"": ""COMPANY"", ""children"": [{ ""text"": ""Fred Shorts"", ""column"": ""CONTACT"" }] } ] }, { ""text"": ""USER"", ""column"": ""CLASS"" } ] }"
Dim o As Object = Nothing
Try
' deserialize the JSON into an Object,
' shout out to: https://stackoverflow.com/a/20080495/1129926
o = jss.Deserialize(Of Object)(jsonData)
o = jss.Serialize(o)
Context.Response.Clear()
Context.Response.ContentType = "application/json; charset=utf-8"
Catch ex As Exception
// log something
End Try
Return o
End Function
On the client I initialized jsTree in script block as follows:
$(document).ready(function () {
var sURL = "../dataIO.asmx/GetJsonData";
var dataIn = "";
$.ajax({
async: true,
type: "POST",
url: sURL,
dataType: "json",
data: dataIn,
contentType: "application/json; charset=utf-8",
success: function (data) {
console.log("data obj:" + data);
createJSTrees(data);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
console.log(XMLHttpRequest.statusText + "(status=" + XMLHttpRequest.status + "): " + XMLHttpRequest.responseText);
}
});
});
function createJSTrees(jsonData) {
$("#jstree_dataNav").jstree({
"core": {
"data": jsonData
}
});
$("#jstree_dataNav").on("changed.jstree", function (e, data) {
console.log(data.selected);
});
}
<div id="jstree_dataNav"></div>
jsTree has a somewhat alternative syntax whereas you call the web service within the core.data section but I was unable to get that to work. Instead, I call my web service via ajax and then pass the JSON data object to a function that initializes the jsTree plugin and jsTree just used the object passed in within data:.
I'm trying to use jQuery and JSON with a C# Web Service that I wrote. No matter what, the following code will only output in XML.
Webservice Code
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public string HelloWorld() {
return "Hello World!";
}
I also have these attributes assigned to the class
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ScriptService]
jQuery Code
$.ajax({
type: "POST",
contentType: "application/json; charset=utf-8",
url: "ScheduleComputerDS.asmx/HelloWorld",
data: "{}",
dataType: "jsonp",
success: function(data) {
alert(data);
}
});
The ASMX page always returns as content type "text/xml". Anything I'm missing?
EDITS: In response to a couple answers:
If I have the datatype as just "json" the content is still XML and jQuery also will not call my callback function. If I add the "&callback=?" to the url, IIS throws a HTTP 500 error.
My class does inherit from "System.Web.Services.WebService".
From doing some research on your guys answers, it looks like I do need to mess with WCF. Unfortunately the JSON that is returned is more designed for MS Ajax and is a lot of useless bloat for my use. I may look into an open source library like Jayrock or something similar.
Thanks for all your help!
I think there's a typo:
dataType: "jsonp",
Should be:
dataType: "json",
As far as I know, the ScriptService attribute just allows the service to automatically create a JavaScript proxy (by appending /js to the endpoint address - ScheduleComputerDS.asmx/js in your case). It does not allow you to call the operations on the service the way you're trying to do.
You could instead use a RESTful WCF service (which requires .NET 3.5) which you can access by sending a properly shaped URI via an HTTP GET.
Rich Strahl has a really basic post that should help you out with this.
http://www.west-wind.com/weblog/posts/164419.aspx
Have you tried with datatype json?
Also, have a look at Encosia's Using jQuery to Consume ASP.NET JSON Web Services article on the matter. There's some good info on common pitfalls too.
I created an ASMX file with a code behind file. It's working fine, but it is outputting XML.
However, I need it to output JSON. The ResponseFormat configuration doesn't seem to work. My code-behind is:
[System.Web.Script.Services.ScriptService]
public class _default : System.Web.Services.WebService {
[WebMethod]
[ScriptMethod(UseHttpGet = true,ResponseFormat = ResponseFormat.Json)]
public string[] UserDetails()
{
return new string[] { "abc", "def" };
}
}
To receive a pure JSON string, without it being wrapped into an XML, you have to write the JSON string directly to the HttpResponse and change the WebMethod return type to void.
[System.Web.Script.Services.ScriptService]
public class WebServiceClass : System.Web.Services.WebService {
[WebMethod]
public void WebMethodName()
{
HttpContext.Current.Response.Write("{property: value}");
}
}
From WebService returns XML even when ResponseFormat set to JSON:
Make sure that the request is a POST request, not a GET. Scott Guthrie has a post explaining why.
Though it's written specifically for jQuery, this may also be useful to you:
Using jQuery to Consume ASP.NET JSON Web Services
This is probably old news by now, but the magic seems to be:
[ScriptService] attribute on web service class
[ScriptMethod(UseHttpGet = true, ResponseFormat = ResponseFormat.Json)] on method
Content-type: application/json in request
With those pieces in place, a GET request is successful.
For a HTTP POST
[ScriptMethod(UseHttpGet = false, ResponseFormat = ResponseFormat.Json)] on method
and on the client side (assuming your webmethod is called MethodName, and it takes a single parameter called searchString):
$.ajax({
url: "MyWebService.asmx/MethodName",
type: "POST",
contentType: "application/json",
data: JSON.stringify({ searchString: q }),
success: function (response) {
},
error: function (jqXHR, textStatus, errorThrown) {
alert(textStatus + ": " + jqXHR.responseText);
}
});
A quick gotcha that I learned the hard way (basically spending 4 hours on Google), you can use PageMethods in your ASPX file to return JSON (with the [ScriptMethod()] marker) for a static method, however if you decide to move your static methods to an asmx file, it cannot be a static method.
Also, you need to tell the web service Content-Type: application/json in order to get JSON back from the call (I'm using jQuery and the 3 Mistakes To Avoid When Using jQuery article was very enlightening - its from the same website mentioned in another answer here).
Are you calling the web service from client script or on the server side?
You may find sending a content type header to the server will help, e.g.
'application/json; charset=utf-8'
On the client side, I use prototype client side library and there is a contentType parameter when making an Ajax call where you can specify this. I think jQuery has a getJSON method.
Alternative: Use a generic HTTP handler (.ashx) and use your favorite json library to manually serialize and deserialize your JSON.
I've found that complete control over the handling of a request and generating a response beats anything else .NET offers for simple, RESTful web services.