Using jQuery to Consume ASP.NET JSON Web Services
AJAX, ASP.NET, JavaScript, jQuery, UI By Dave Ward on March 27th, 2008
In response to many of the articles here, I receive feedback asking how to achieve the same results without using ASP.NET AJAX. As much as I’m a fan of ASP.NET AJAX, I must agree that its JavaScript payload can certainly be a drawback in some situations.
My recent deferred content loading post is an excellent example of that. I was using jQuery for presentational effects, and using a ScriptManager to call a web service. Loading the JavaScript for both frameworks was a bit counterproductive, since the whole point was to improve initial load time.
In this post, I intend to correct that.
First, I’ll cover the two requirements necessary when calling an ASMX web service that’s being JSON serialized by the ASP.NET AJAX extensions. Then, I’ll show you how to do this with jQuery. Finally, I’ll update the deferred content loading example accordingly.
Additional security when calling JSON serialized services
A security feature of ASP.NET web services that are JSON serialized through the ASP.NET AJAX extensions is that they must be requested in a specific way. This is an important deterrent against your services being used in XSS attacks. Scott Guthrie has a great post providing detailed information on the particulars. It boils down to is two things:
- The request must be an HTTP POST request
- The request’s content-type must be: “application/json; charset=utf-8″
When you register and call a web service through ASP.NET AJAX’s ScriptManager, you may safely enjoy blissful ignorance of these requirements. The framework transparently handles everything for you.
However, if you want to use a third party AJAX framework to request the JSON serialized output, you may run into trouble due to these security features.
How to make jQuery jump through these hoops
The solution is a bit less intuitive than using the ScriptManager or what you would normally expect from jQuery. Using jQuery’s getJSON() would make sense, but it unfortunately meets neither of the above security criteria.
The most reliable way that I’ve found is to use jQuery.ajax() as follows:
$.ajax({ type: "POST", contentType: "application/json; charset=utf-8", url: "WebService.asmx/WebMethodName", data: "{}", dataType: "json" });
As you can see, the first parameters set the request type and content-type as required by the ASP.NET AJAX framework.
When making a read-only request, the empty data parameter is the key. For reasons unknown, jQuery does not properly set the specified content-type when there is no data included.
The “{}” data parameter represents an empty JSON object, which you can think of as the JSON equivalent of null. Supplying this parameter will convince jQuery to correctly send the content-type that we’ve supplied, while it will be safely ignored by the web service.
If you’d like to see a closer examination of why this particular syntax is used, you’ll be interested in 3 mistakes to avoid when using jQuery with ASP.NET AJAX.
Putting it all together
Now that we know how to call the web service, appropriately modifying the original example is easy. Here’s the new ASPX code:
<div id="Container"> <div id="RSSBlock"> <div id="RSSContent" class="loading"></div> </div> <div id="Content"> <p>Lorem ipsum dolor sit amet, consectetuer adipiscing...</p> </div> </div> <script type="text/javascript" src="jquery-1.2.3.min.js"></script> <script type="text/javascript" src="Default.js"></script>
Notice that I’ve placed the JavaScript references below the rest of the page’s content. Since browsers block while requesting, loading, and executing JavaScript, it makes sense to defer that until as late as possible. This will serve to further boost the page’s perceived performance.
Finally, the jQuery code to call the web service and appropriately handle its result:
$(document).ready(function() { $.ajax({ type: "POST", url: "RSSReader.asmx/GetRSSReader", data: "{}", contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { // Hide the fake progress indicator graphic. $('#RSSContent').removeClass('loading'); // Insert the returned HTML into the <div>. $('#RSSContent').html(msg.d); } }); });
Conclusion: Is it worth it?
By using jQuery to call the web service directly, we’ve eliminated over 100 KB of JavaScript and three extra HTTP requests. The ASP.NET AJAX client side framework accounted for over half of the original example’s total download size, and those three extra HTTP requests unnecessarily delayed the progress indicator.
That may not sound like much, and I generally agree that premature micro optimization is a wasteful habit, but it’s significant in this case. When it comes to loading speed and responsiveness, users don’t perceive changes linearly. Fractions of a second make the difference between a site that feels sluggish and one that appears responsive.
A word about web services
Web services are great tools that afford you substantial flexibility. It’s important not to overlook them.
You’ve no doubt seen many AJAX examples that involve using the XmlHttpRequest to request the output of a specially designed page, resulting in CSV or otherwise arbitrarily formatted data instead of HTML. For instance, I’ve noticed that a lot of the auto-complete plugins for jQuery expect this sort of kludge.
I believe that to be a short-sighted and counterproductive way to do things.
Web services have often been maligned in the past, due to the XML bloat associated with SOAP. However, JSON makes this drawback a thing of the past. JSON is very lightweight, making it ideal for structured AJAX communication. With the inefficiencies of SOAP neutralized, I think the power and flexibility of web services cannot be overstated.
For example, if I decide to move my sites from WebForms to MVC, there is a large amount of functionality encapsulated in web services that I won’t have to worry about recoding or redesigning. It’s a great feeling to have that flexibility and ease of reuse.
Try it for yourself: download the source
The full example’s source code (ASP.NET 3.5 required):
Similar posts
What do you think?
I appreciate all of your comments, but please try to stay on topic. If you have a question unrelated to this post, I recommend posting on the ASP.NET forums or Stack Overflow instead.
If you're replying to another comment, use the threading feature by clicking "Reply to this comment" before submitting your own.
32 Mentions Elsewhere
- Dew Drop - March 27 | Alvin Ashcraft's Morning Dew
- Reflective Perspective - Chris Alcock » The Morning Brew #61
- March 28th Links: ASP.NET, ASP.NET AJAX, ASP.NET MVC, Visual Studio, Silverlight, .NET « .NET Framework tips
- Enlaces de Marzo: ASP.NET, ASP.NET AJAX, ASP.NET MVC, Visual Studio, Silverlight, .NET « Thinking in .NET
- Wöchentliche Rundablage: WPF, Silverlight 2, ASP.NET MVC, .NET 3.5… | Code-Inside Blog
- Using jQuery to consume JSON Services « HSI Developer Blog
- Links do dia 28 de Março: ASP.NET, ASP.NET AJAX, ASP.NET MVC, Visual Studio, Silverlight, .NET - ScottGu's Blog em Português
- Eye On .NET - Hisham Elbreky
- Using jQuery & JSON with ASP.NET at KeithRousseau.com
- Using jQuery to Consume ASP.NET « vincenthome’s Software Development
- 3 mistakes to avoid when using jQuery with ASP.NET AJAX
- jQuery with ASP.NET Json Web Services : { null != Steve }
- Mi primer plugin de jQuery = jQuery.dotNet « Walter Poch
- Good links: ASP .NET and JQuery - Programmatically Speaking ...
- My Portal Project » Blog Archive » ASP.NET Web Services from Javascript with jQuery (without the ScriptManager)
- Elegant Code » Calling Remote ASP.NET Web Services from JQuery
- Submitting an AJAX Form with ASP.NET MVC + jQuery « {Programming} & Life
- JavaScript Arrays via JQuery Ajax to an Asp.Net WebMethod | Elegant Code
- Integrating SmartGWT with ASP.NET JSON web service « Reminiscential: of or pertaining to remembrance
- JQuery Resources
- jQuery and ASP .NET MVC: browser issues | peterskim
- Amr ElGarhy » How I handle JSON dates returned by ASP.NET AJAX
- jQuery Tutorials ( Learn – Practice – Expert ) « Ramani Sandeep
- jQuery autocomplete plugin with ASMX web service and JSON « Adam Mokan's Development Blog
- links for 2009-12-23 « 2LeggedSpider
- Building an AJAX web part with jQuery (Part 2)
- Consuming a JSON WCF Service with jQuery « Me Too on .NET
- Using XML, LINQ and jQuery for a Google Maps Store Locator « Sam's Daily Life
- WCF and JSON « Wibber's Blog
- adam mokan / jQuery autocomplete plugin with ASMX web service and JSON
- ASP webservice in jQuery « Izdelava spletnih strani Blog
- ASP.NET JQuery AJAX « Code Kat ^..^



We had been thinking about doing this with some of the stuff at my work. We love jQuery, but at the same time we wanted to call out to .net web services or web methods. Have you tried to do this same setup with [WebMethod] and [ScriptMethod(ResponseFormat = ResponseFormat.Json)]? I’ve never looked at it, but I would imagine that these methods could be call in a similar fashion to web services.
I probably wasn’t clear in my last comment, I am talking about page methods in the code behind.
I haven’t tried it, but I think the request is similar and it would be doable. You would just point the request at Page.aspx/PageMethodName.
Thank you for that, it was pretty clear and your notes in the middle as well as comparison with ASP.NET AJAX style were very clear and useful
Great post! I’d be very interested to see about that page method + jQuery piece you and Justin are talking about.
Re: Page Methods. I tested it out, and you can definitely call them the exact same way.
I removed the ScriptManager and UpdatePanel from my Why UpdatePanels are Dangerous post, added jQuery, and used this code to call the page method:
It worked, just like the example above, replacing the JavaScript proxy generated by setting EnablePageMethods to true on the (now removed) ScriptManager.
Good idea, Justin. I hadn’t even thought to try that, myself.
Sweet. Glad that worked. It will certainly come in handy in the future.
How are the webmethods serialized into JSON? I notice you use msg.d. If you switch the datatype in the jquery called to text it reveals the json string {“d”:”…”} for the msg. Where is “d” specified?
The “d” is a function of how ASP.NET AJAX returns JSON serialized data. The “d” acts as a container object.
Hi.
What if I want to pass complex data(js object) into jQuery ajax call?
I haven’t had a chance to try that yet.
The way I’d suggest going about figuring it out would be watch the request in FireBug or Fiddler, using ASP.NET AJAX on the client. You’ll see what gets POSTed, then can replicate that in the jQuery call’s “data” parameter.
Great find Dave. I guess JQuery is more useful than I imagined.
I agree
hi Justin,
very good article indeed.
1 Question – would this approach work for image/binary data retrieval from REST style webservices ? I Mean can we set the dataType as binary or JPEG ?
Typically, for serving binary data like that, I’d suggest looking into an ASHX handler on the server side.
On the client side, you could asynchronously request new data through that handler by updating the src of an img tag (or whatever element you’re displaying the binary data in).
Dave, you are not alone. I also removed ScriptManager and UpdatePanel and used jQuery instead. Works like a charm. In production environment. The difference is that I retrieve data from HttpHandler.
2Anatoly: You can send any object which can be serialized to JSON (i.e. name-value pair combinations). After calling eval() on client side you work with result like it’s an object:
var data = eval(‘(‘ + result + ‘)’);
var msg = data.Result.Message;
As for binary, I ran into the following problem: it’s pretty normal that binary data goes with another content-type. Unfortunately, jQuery offers access to XHR (XMLHttpRequest object) and its getResponseHeader method in ‘complete’ event when ‘success’ with data processing has already passed. Does anybody know the work around?
Thanks Igor
Dave, this looks good. One thing you probably would want to mention though is how to send JSON *to* the server as a parameters as well. jQuery doesn’t do JSON natively and MS Ajax requires some special ‘wrapped’ formatting.
You can do this by wrapping parameters into MS Ajax’s JSON format (outer class with parameters as properties) and using a JSON library like Crockford’s JSON2 library. In many cases this parameter passing gives more of a service feel to the application and would allow you to pass ‘complex’ types around with parameters directly received by the service or page methods.
Same approach also works with the new WCF REST services.
Hi Guys
I am trying an example similar to the one above but I am getting an invalid JSON primitive error. I have a local web service working fine and I’m attempting to retrieve a string from it. My code is not reaching the debug in the web service because it fails in the javascript beforehand with the error below.
{“Message”:”Invalid JSON primitive: origin.”,”StackTrace”:” at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializePrimitiveObject()\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize
(String input, Int32 depthLimit, JavaScriptSerializer serializer)\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.ArgumentException”}
===============================================================
here is my ajax code…
===============================================================
$.ajax({
type: “POST”,
data: “origin=” + $(“#origin”).val() + “&destination=” + $(“#destination”).val() + “depDate=” + $(“#depDate”).val() + “&retDate=” + $(“#retDate”).val(),
url: “/WebServices/KayakService.asmx/GetFlightSearchId”,
beforeSend: function(xhr) {
xhr.setRequestHeader(“Content-type”,
“application/json; charset=utf-8″);
},
dataType: “json”,
success: function(msg) {
searchId = msg;
alert(‘Search ID = ‘ + searchId)
}
});
Has anyone ran into anything like this before?
I believe the problem is that your “data” isn’t proper JSON. As Rick mentioned above, you can use the JSON2 library to help automate that process.
Take a look at this page for more info: http://www.json.org/js.html
The library is linked at the bottom of that page.
In your particular example, try changing your data parameter to:
Hi Dave
Still getting the same error after making the suggested change, will try that json2 library out tho cheers.
Mart
Sussed it Dave – I just needed to escape everythin like this…
data: ‘{“origin”:”‘ + $(“#origin”).val() + ‘”,”destination”:”‘ + $(“#destination”).val() + ‘”,”depDate”:”‘ + $(“#depDate”).val() + ‘”,”retDate”:”‘ + $(“#retDate”).val() + ‘”,”sessionId”:”‘+ sessionId +’”}’,
Just realised, this only works in Firefox, it fails in IE7 every time. I can’t seem to find out the error either, IE7 must not like the JSON format perhaps?
The JSON formatting should be the same between browsers. Are you getting a JavaScript error from IE?
Hi Dave
I’m not getting a javascript error, the ajax call just fails with no message.
I narrowed the code down and produced a simplified version and I think that it is definitely the ‘data:’ line that causes the issue.
try your example again but add in a data: block to pass a simple param. It works in both IE7 and Firefox without the ‘data:’ line but as soon as you put it in, it only works on FireFox.
I simplified mine to accept 1 param which I put as
data: ‘{“name”,”dave”}’,
this was enough to make it only work on firefox.
Cheers
Mart
Hi Dave
Did you manage to suss this one out for me? It’s a proper showstopper at the minute.
Mart
Martin, I’ve been able to reproduce the problem here, and think I’ve cured it. What I believe I found to be the problem is a bit bizarre though, so I want to make sure I’m correct.
Could you email me the modified version that you’re using, which reproduces the issue?
Hi Dave
I’ve sent you a zipped sample project with everything narrowed right down.
Thanks a lot
Mart
It turns out that IE7′s XmlHttpRequest implements setRequestHeader as an appending function instead of a replacement.
Because jQuery does set the content-type on POST requests that have data, the content-type gets set to the default “application/x-www-form-urlencoded” initially. Then in IE7, setRequestHeader was adding “application/json; charset=utf-8″ to that instead of truly setting it. So, the content-type was incorrect for JSON serialization and the web service was returning XML instead of JSON.
Bottom line, replace this:
With this:
Just keep in mind that you can only do this on calls that have POST data. If you’re making a read-only call, like in my example, you must still use the beforeSend method to set the content-type.
Dave! you’re an absolute star mate – nice one!
Mart :D
hey dave, just one detail that i didn’t realize before i started to mimic this was that the variable name on the web service and the json object key, have to be the same. i kept getting an error before i did this.
I’m having a trouble serializing a date.
Microsoft ASP.NET AJAX serialize DateTime objects using UTC format.
This is the format: \/Date(UTC TIME)\/.
For example \/Date(1208644401687)\/.
I’m trying to serialize a date using json2.js from http://www.json.org before passing it to the $.ajax call. This is the code:
var dat=”\\/Date(1208644401687)\\/”;
var myData={title:”hello”,data:dat};
var myDataSerialized = JSON.stringify(myData);
dat has a value of \/Date(1208644401687)\/ but when serialized it becomes \\/Date(1208644401687)\\/. I don’t understand why json serializer adds 2 backslash. It seems there’s no way to serialize a date in the correct format. Any suggestion?
I’m having the same problem, however this problem only exists in .net 2.0 because 3.5 seems to accept the “2008-06-26T10:20:06Z” format which means you can just use the JSON.stringify on new Date() and it will work fine, however not in 2.0.
I’m trying to figure it out. Hopefully i will get somewhere.
Hey, Dave, greeeeat post! Also Rick has some good points and great article on his site. Keep up good work guys, it really help me.
Dave and crew… I wanna ask your opinion on some stuff. My imagination has ran wild since the birth of jQuery and ajax. At the moment I want to recode all my asp.net postback work into an ajax / jquery style framework.
The reason i wanna do this is to increase the WOW factor of websites. No longer do people need to wait for that predictable flicker while they are presented with the data they want.
With lazy load of API javascript code and the like we have a platform to do what the hell we want to??? or am i much mistaken? – The possibilities in my head are endless at the minute. Enough to make me no longer need the code behind model of ASP.NET or even the AJAX part of ASP.NET for that matter (overbloat???).
Someone please bring me back down to earth before i get carried away….
Marv
I believe websites will completely change their underlying technology over the next few years, in an attempt to overcome the standard boundaries of web dev and this will spill into what everyone knows today as TV……..
Mark my words.
The Dannster (write this down)…..
I say: Get carried away!
The one thing I would suggest is waiting on the ASP.NET MVC framework to be fully released. If you’re going to start rewriting pages anyway, rewriting them MVC is going to be the way to go.
Once you get your head wrapped around the MVC methodology, it’s a thing of beauty. There’s no going back. MVC meshes very well with the idea of using RESTful web service calls to provide a rich client-side interface to your app.
Must agree that MVC makes it super simple to use jquery to call back end.
see NerdDinner for example.
Hi, I’m getting the same error message Martin was reporting. What was the final resolution? Parameterless methods work, I only hit a wall with parameters. Any help would be much appreciated.
I believe jQuery requires a string argument for “data”. Try this instead:
It’s the web service itself that will take the JSON string and parse it out, on the server side.
I’m having the same problem. Regardless of how I create the data, I just can’t get it passed into a page method.
I posted a question on stackoverflow, but there hasn’t been any answers after 2 days. Is this actually possible?
Cracked it. Data needed to be passed as a string.
Great post, thanks. Rich
hi there,
i have been postponing my Jquery Json learning for too long.
but i am tackling it now, no more excuses.
I also have to mention, i still working on the net 2.0
could you give us some pointers on how to get this one to work in 2.
i understand the whole, although been reluctnt to swap to ajax development for too long and after review your webconfig i get a bit lost.
any pointers on where to get the concrete info for me to know how to enable json with asp.net 2.0 in my webconfig.
thanks,
Dave
This documentation will help you get your web.config set up for using ASP.NET AJAX with 2.0:
http://www.asp.net/ajax/documentation/live/ConfiguringASPNETAJAX.aspx
I’m trying to get this to work while passing in HTML code as a string. The reason is the following: I’m attempting to store a block of html code in a database that can be modified by the user throughout the site without doing a full page postback. using javascript seemed to be the best solution, however, it fails with an invalid formatted string.
This is the data: val
Any ideas on how i would successfully pass this param through?
The double quotes in your HTML string are breaking the JSON literal. Look into HTML encoding in JavaScript, and you’ll find some techniques to handle that.
FIXED! Thanks so much!
When calling asp.net webservices with jQuery, would you need to do something special to be able to access Session data or user specific data, like membership, account properties etc.?
In order to access the session from a webservice, you need to amend the WebMethod take like so:
using jQuery resolves some problems and eases the process somehow
Thanks for the article Dave.
As discussed above ASP.NET 3.5 packages the JSON payload in a “d” object. JSON string {â€dâ€:â€â€¦â€}
Does this mean that Javascript callbacks can’t be used with ASP.NET 3.5? My understanding that cross domain information exchange depends on running eval on the returned payload.
Any information would be appreciated.
That’s correct.
The msg.d form is to prevent XSS attacks, by preventing malicious user submitted data from being arbitrarily executed via eval.
If you want to implement a JSONP capable service, you’ll need to roll your own serializer. JavaScriptObjectSerializer makes this relatively easy though, once you get into it.
I do wonder if JSONP will be with us for the long-term or not. If big name services like Flickr didn’t adopt it early, it probably would’ve been treated as a security issue and fixed in most browsers by now.
#1 – great writeup, fantastic to get a clear/concise and simple example of how to invoke simple ASP.NET exposed WebMethod’s through jQuery.
This ASP.NET DateTime JSON serialization issue I think I have a solution for. I outlined the solution as well as a regurgitated version of this original post at: http://www.overset.com/2008/07/18/simple-jquery-json-aspnet-webservice-datetime-support/
The solution is to pre-parse the DateTime JSON string response from the WebMethod/WebService before jQuery essentially eval()s it:
$.ajax({
// …
dataFilter: function (data, type) {
return data.replace(/”\\\/(Date\([0-9-]+\))\\\/”/gi, ‘$1′);
}
});
Thanks again – this has writeup is fantastic!
Fine stuff. I downloaded the source code and noticed that the RSSReader.asmx is in the Root, but RSSReader.asmx.cs is in /app_code. Is this standard practice to split web service files?
Thanks again!
It’s how Visual Studio splits the files by default, when using a website project. When using a web application project, it will keep them together.
Personally, I prefer the latter. However, since VWD Express doesn’t yet support web application projects, I use the former for code samples.
Thank you for sharing so great stuff here.
But I met a problem when trying to set up your demo.
{â€Messageâ€:â€Invalid JSON primitive: origin.â€,â€StackTraceâ€:†at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializePrimitiveObject()\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.DeserializeInternal(Int32 depth)\r\n at System.Web.Script.Serialization.JavaScriptObjectDeserializer.BasicDeserialize
(String input, Int32 depthLimit, JavaScriptSerializer serializer)\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.ArgumentExceptionâ€}
That indicates a problem with your “origin” data parameter in the $.ajax() call. Double check that it’s properly quoted, like:
I just found bug in jquery 1.4.1 when i get from web service string “{“d” : “hello world”}”.
I did debug in firebug and found when it came to
* httpData: function( xhr, type, s ) {.. *
it goes to line:
* data = jQuery.parseJSON( data ); *
and then in parseJSON we get error from line:
* jQuery.error( “Invalid JSON: ” + data ); *
My request was set as you suggest:
$.ajaxSetup({
type: “POST”,
contentType: “application/json; charset=utf-8″,
data: “{}”,
dataFilter: function(data) {
var msg;
if (typeof (JSON) !== ‘undefined’ &&
typeof (JSON.parse) === ‘function’)
msg = JSON.parse(data);
else //less secure but necessary
msg = eval(‘(‘ + data + ‘)’);
if (msg.hasOwnProperty(‘d’))
return msg.d;
else
return msg;
}
});
$.ajax({
url: wsUrl+”/HelloWorld”,
success: function(msg) {
console.log(msg);
$(‘div #content’).removeClass(‘loading’).html(msg);
}
});
I then replace jq with 1.3.2 version, and it is fine, also debug and see that code in line:
* httpData: function( xhr, type, s ) { * is different.
Thanx, Goran from Belgrade
hi Dave, great post, really useful. I am having a small issue though, I am using jQuery to call a webservice and then creating a .ascx class to create the preformatted data. The only difference is I am sending a simple ID paramater, I’ve had no problem with passing through jQuery but how would I send the parameter from the web handler to the .ascx class?
In my web handler i have tryed
Page page = new Page();
UserControl ctl = (UserControl)page.LoadControl(“PlayersReaderControl.ascx?uniqueID=”+int.parse(uniqueID));
but with no luck, please help! Thanks.
ive figured it out, was really simple. just had to set an attribute variable for the user control then retrieve it.
Very cool. This was very very helpful to me! Thanks!
Hi Dave,
Just a quick question. In your opinion, is it advisable or secure to pass a JSON string to an ASP.Net web service? For example, I have a registration form where there are fields like user name and password. Or, another example would be a login form.
Thanks!
Since a password is involved, I would only do that if the service call was SSL. That stipulated, sure. It wouldn’t be inherently any more or less secure than a postback.
Thanks and great post by the way.
I’d just like to say that this article has had the most commendable group of contibutors I have ever seen in a technical discussion and you should all be thoroughly congratulated and used a gold standard for all other discussion groups.
Thanks to all of you for a great experience, and of course thankyou Dave for the article – i’m loving the speed.
Thanks a lot for this article. Its really amazing! I downloaded the sample and its working perfectly. But when i tried using the same concept, I was getting ajax error as some people above posted. I am using RssToolKit for reading rss feeds. When I try to debug the code, the ajax error comes first. The string builder in webservice.vb shows the rss feeds but it does not return to aspx. Can anyone tell me what I should do to rectify the issue?
Specifically, what JavaScript error are you getting?
Hi, guy. do you think there is any limitation in this solution, for example, the SEO is not great due to that your content is dynamic built. any advices?
You should not defer loading of any content you want to rank for. Any kind of deferred loading is going to remove that content from what the search bots see (at least for now).
The idea here is to defer loading of ancillary content, so that the core content – what you really want to rank for and what the user cares most about – can load faster.
The original post talks more about the whys instead of the hows, as this one is more about jQuery.
thanks a lot, I got it. This technique is very powerful for the content which are not rank for. :)
Just as an FYI, I got this approach to work on a non-AJAX enabled ASP.NET site.
can u help?
I downloaded the cide and opened it
I get error
Error 1 Could not create type ‘RSSReader’. UCDelayLoad\RSSReader.asmx 1
I have framework 3.5
thanks
Hey Dave,
First off great article! I have setup a test app that is working perfectly but only if the function is called one at a time. If, however, multiple calls hit the js function the $.ajax call defaults to the error function. Is there a way that the js function running the $.ajax call can be called by many different pages at the same time? One of our sites is HTML but also is a store front, I would like to use this method display customer cart info on the HTML pages e.g. Cart(2) $54.12.
Please let me know if you have any insight on this. I am using .NET 3.5 WS2003 and calling the data from a web service.
You can definitely make multiple, concurrent calls to the service.
I’d suggest finding out what specific 500 error is returning from the server (this is what causes $.ajax to enter the “error” handler), and using that to narrow down what server side code is throwing the error.
Hello Dave, I fixed the error above… it had to do with the API I was getting the cart data from.
But a new problem with FF. I am using jquery 1.2.6 and am getting this error in FF3:
Error: [Exception... "Access to restricted URI denied" code: "1012" nsresult: "0x805303f4 (NS_ERROR_DOM_BAD_URI)" location: "/js/jquery-1.2.6.min.js Line: 28"]
Source File: file js/jquery-1.2.6.min.js
Line: 28
This works fine in IE7, any ideas?
OK, so I know this error has to do with cross domain calls. Does this mean it will not work with sub-domains either?
That’s right. XmlHttpRequest doesn’t make cross domain calls by default (for very important security reasons). I’m surprised it worked in IE either.
If you have no choice but to work with a service on another domain, you’ll need to create a proxy service on the domain where your page resides to act as a go-between.
hmmm… for some reason I thought it worked on a sub domain eg ws.domain.com when the page is at http://www.domain.com/page.html. Thanks for the info, very informative website!
Hello Dave, I have been googling all weekend looking for a good article on setting up a proxy so I can get this to work without loosing out on security. Do you know of any? Maybe be a good article for you to cover as I have found any people with the same question but no answer. (cross-domain webservice calls with jquery & asp.net)
Hi Paul,
If I understand the question properly, you want to know how to create a proxy for a web service on a different domain.You can do this a couple of ways but adding the service as a web service in your ASP.NET project is the easiest.
For ASP.NET 2.0
Right click project name and click ‘Add Web Reference’. Type in the URL of the web service and a namespace name.
For ASP.NET 3.5 sp1
Right click project name and click ‘Add Service Reference’, then click ‘Add Web Service’ (I think) at the bottom of the dialog. Then follow the 2.0 instructions as if you had just clicked ‘Add Web Reference’.
Now you are free to create your own web methods to act as wrappers for the newly created namespace.
Rich
If you want to call the .NET service with an HTTP GET, you can use the “beforeSend” method of jQuery’s ajax object to modify the properties of the XMLHTTPRequest object directly:
$.ajax({
beforeSend: function (XMLHttpRequest) {
XMLHttpRequest.setRequestHeader(“Content-Type”, “application/json”); },
type: “GET”,
url: “/services/MyService.ashx”,
dataType: “json”,
success: function(msg){ $(“#myDiv”).text( “Data Received: ” + msg ); }
});
You really shouldn’t have to set a Content-Type header if you are using GET, but I guess we have to play by ASP.NET rules…
This post actually used the beforeSend form originally, but it turns out not to be reliable in every situation.
Unfortunately, for GET requests using beforeSend is the only way to specify correct content type (at least for me none of other options worked out).
And thank you for the great blog, of course.
Hi Dave
Great article (one of many I’ve found useful on here), my question is I have a WebService method that loads a usercontrol and spits out the generated html so I can dynamically add these into the page. However what I would like to do is passing some querystring variables through when I’m loading the user control. do you know how or even if this is possible using jquery?
Cheers
Hi,
If you are talking about passing variables from the server to the client at page load, you can do a couple of things.
1. In PageLoad (or similar) add a dynamically created script block with all of your variables declared.
Page.ClientScript.RegisterClientScriptBlock(typeof(UserControl), “UserControlName”, “var variable = ” + 1 + “;”, true);
2. Take a look at jQuery’s Metadata plugin. Using this plugin you can put the variables right in the generated HTML. The plugin can be found here.
Rich
Sorry my post may have been a bit confusing.
I want the querystring variables posted to the page load method of the user control. So when the user control is loaded I can populate controls within it before it’s then passed back to the browser as pure html.
Hope that make sense ;-)
You can access the querystring from Page.Request.QueryString within the user control.
Rich
here is my jquery method
function WSClicked() {
$.ajax({
type: “POST”,
contentType: “application/json; charset=utf-8″,
data: “{path:’controls/TestControl.ascx’}”,
dataType: “json”,
url: ‘Services/Ajax.asmx/RenderUC’,
error: function(XMLHttpRequest, text, error) {
$(“#WSResult”).text(XMLHttpRequest.responseText);
},
success: function(msg) {
$(“#WSResult”).html(msg.d);
}
});
}
I’m trying to achieve the same as this article (http://samuelmueller.com/post/2008/12/20/Dynamically-Loading-ASPNET-User-Controls-with-jQuery.aspx) except using a web service. I’m just not sure on how to pass variables from jquery so that they are accessible in the Request.Querystring of the Page_Load of the user control.
Can’t you just chuck the query string on the end of that usercontrol url?
This is an example of using a web service (and you can also do this in a page method the same way) to instantiate a user control and render it as HTML:
http://encosia.com/2008/02/05/boost-aspnet-performance-with-deferred-content-loading/
To pass a parameter to your user control, add a public property to the user control’s class (in the code-behind), pass that data to your page method or web service, and then set that property before rendering the control.
Can’t you just chuck the query string on the end of that usercontrol url?
no it dies when Page.Load(“path of control”) is called as it can’t find the address because of the “?action=load” on the end
Hey Dave,
Is it possible to pass a generil List as parameter to the Method?
so that i got a method in the webservice like
public bool Something(List){
…
return true;
}
thanks
dave
I have managed to pass a .NET class to a ASMX ScriptMehod but not to a WCF Endpoint. I’d be interested if it is possibe or not.
If you add the AspNetCompatibilityRequirements attribute to your WCF service classes, you can get the same serialize/deserialize functionality that ASMX “ScriptServices” provide.
Sorry, I cracked it.
I was trying to pass a .NET class to a WCF Endpoint using the GET Verb, but couldn’t get it work. Once you replied I took another look at firebug and realised that I wasn’t encoding the # in the __type property.
Once encoded to %23, the code worked fine.
Yes. The JavaScript counterpart of a List (or any collection) is an array. For example (assuming my syntax is correct), you could pass:
As the data parameter to call a function declared as:
Generally speaking, I’d suggest using an array as the parameter type on the .NET side. It’s less overhead and it’s a bit more clear later.
hi all
if u all are experiencing the same problem as me my flash cant get data from json on ie7.
just escape ur parameter.
e.g param:escape($.toJSON(data))
thanks sherrymerry
great article
Hi Dave,
By calling web services via. jquery, we are specifying url of the webservice right in the source. So, will it not be easy for others to just look at it and add a reference to the web service and make fake calls to the webservice.
Actually I am implementing this type of call when user isn’t authenticated, so no ticket is passed over the network to check the validity of the request.
Could you tell us what would be the basic security measures we can incorporate in the appln.
Thanks,
Sundeep.
ASMX services are very similar to ASPX pages in terms of security issues. You can secure them the same way (e.g. forms authentication, session state, etc).
Thanks for the reply.
As I mentioned earlier, in that particular aspx page user is not authenticated via forms authentication.
I would like to expand on this, please correct me if I am wrong.
Say I had written the code: Response.Write(“Hello”);
in the code behind of aspx page. I needn’t check whether user is authenticated or not.
Same thing when I expose through a webservice like In webmethod: return “hello”;
Anyone can add reference to this webservice and call this method.
Its just an example to put my concern. I don’t want anyone (un-authenticated users) to use the web services.
… very informative
Hi Everybody,
under ASP 3.5 my web service call from jquery ajax succeeds WITH and WITHOUT parameters, no prob at all.
Unfortunately my client runs asp.net 2.0 and I run into following probs:
- contentType: “application/json; charset=utf-8″,
is never accepted by my web service (.net 2.0) and I get following error:
System.InvalidOperationException: Request format is invalid: application/json; charset=utf-8.
at System.Web.Services.Protocols.HttpServerProtocol.ReadParameters()
at System.Web.Services.Protocols.WebServiceHandler.CoreProcessRequest()
- I can change the contentType to: text/xml or application/x-www-form-urlencoded and the web service succeeds AS LONG AS I DO NOT pass in any paramter data meaning my web method cannot have any parameters (like: MyWebMethod(int Count){…}
Once I start and add a parameter to my web method my web service returns the message that the parameter is missing from the ajax call even if I filled in the data: field in the jquery ajax call.
That makes sense because I did not specify that my contenttype is json.
Any ideas why I run into these probs with ASP.NET 2.0? I have installed the AJAX web extensions 1.0, so that can’t be an issue.
Thanks
Franco
Have you installed ASP.NET AJAX 1.0 on the server running 2.0, and updated the site’s web.config accordingly?
Also, keep in mind that once you get it working under 2.0, the .d in the return value won’t be present.
Just add to the web.config in section this lines:
_httpHandlers_
_remove verb=”*” path=”*.asmx”/_
_add verb=”*” path=”*.asmx” validate=”false” type=”System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35″/_
_/httpHandlers_
$.ajax({
type: “POST”,
url: “WebService.asmx/SendName”,
data: “{‘firstName’:'Chris’,'lastName’:'Brandsma’}”,
contentType: “application/json; charset=utf-8″,
dataType: “json”,
success: function(msg) {
}
});
[WebMethod]
public static string GetDate(string firstName, string lastName)
{
return string.Format(“{0},{1},{2}”, firstName, lastName, DateTime.Now);
}
Using this when using parameters
Dave,
I notce that your examples always access the returned json as msg.d.Property. However, this doesn’t work for me. I have to eval it fot it to work: $.ajax({
type: “POST”,
contentType: “application/json; charset=utf-8″,
url: “Client/ws.asmx/GetDetails”,
data: “{‘dId’:'” + id + “‘}”,
dataType: “json”,
success: function(result)
{
var parsed = eval(“(” + result.d + “)”);
$(“#” + elementId).html(parsed.Details);
}
});
Otherwise I get the dreaded undefined. Is that right?
It sounds like you’re manually serializing and returning a JSON string in your web method. Is that the case?
No, I have a helper class that uses the framework methods. I use both of these:
public static string ToJson(this object obj)
{
JavaScriptSerializer js = new JavaScriptSerializer();
string s = js.Serialize(obj);
return s;
}
public static string ToJson(this object obj, Type type)
{
string jsonString = string.Empty;
DataContractJsonSerializer serializer = new DataContractJsonSerializer(type);
using (MemoryStream ms = new MemoryStream())
{
serializer.WriteObject(ms, obj);
jsonString = Encoding.Default.GetString(ms.ToArray());
}
return jsonString;
}
My WebService method does this: return myobj.ToJson();
I’ve favored the javascript version because it handles List a lot easier.
What’s happening is you’re serializing the object and returning a string, but that returned string is also being serialized as JSON. The framework automatically handles that for “ScriptServices”.
If you return your object directly (return myobj instead of return myobj.ToJson()), ASP.NET AJAX will automatically JSON serialize it for you and you won’t need the extra eval().
That was it! Thanks. It’s funny, I had never seen/noticed that details before.
I just can’t seem to get this jquery/flexigrid thing working. :-(
I have a wcf rest svc that returns a list of x, example JSON:
{“CategoryList”:[{"Carrier":null,"Category":"Sample Kit","Dscr":"AID Sample Kit","FormCode":"AIDSampKit","MktgAppCode":"Sales","OccasionCode":"Prospect","ProductionPrice":0,"SubCatgory":"9x12","Uri":null,"psLength":0}]}
I access that list via a call to a websvc:
http://192.168.1.8/C2M/SlsOrderSvc.svc/json/clients/AIDmv0xl2h50/catalog/list
which returns a nice JSON formatted list of values, each and every time.
I just can’t get FlexiGrid to display them.
Is there some documentation that tells me if FlexiGrid needs to have the data formatted a certain way? Or contain certain fields/values?
Do i have to use a table to get FlexiGrid to be able to display the data and do I have to feed it row by row?
I would think that I could just point FlexiGrid at a datasource (web svc call that returns JSON formatted data) and it would be happy.
I have seen many examples of how to do this for C#/VB.Net/ASP.Net and JavaScript, but I can not seem to make it work.
I can nicely use JavaScript, Ajax and a Template and iterate the JSON response and get a nicely (simple) formatted table on the web page…
But I’d rather have FlexiGrid.
So where is this FlexiGrid manual that I have not been able to find?
Thanx,
G
I haven’t used FlexiGrid, so I’m not familiar with its quirks.
For a better supported/documented jQuery grid, you might want to try jqGrid or DataTables.
Dave,
Thanx, checking it out now.
G
Hi Dave,
Just one quick question. I have an application set up that needs to read data from a webservice located on another domain (www.webservicex.net), but it only returns XML and not JSON. Im aware of the XSS issues, and I also found out that an ‘xml’ dataType won’t work in FireFox, but will in IE. What would your suggestion be in this case? The application is intended (as always) to be 100% accessible and needs to work cross-browser. If needed, I can send you the code that I currently have. Ever since I started using jQuery I’ve been hooked. If I can learn properly how to replace all my UpdatePanel functionality using jQuery alone, it will benefit me greatly! TIA!
I have one BIG problem. Even though my sample code works just great on the same machine calling a dotnet ASMX file, as soon as I call the URL from a different machine, nothing works and I get an error saying my URL ended in some wrong way. To be exact, this is the error message – “Request format is unrecognized for URL unexpectedly ending in ‘/HelloWorld’.” But I don’t get this error message if I am on the same machine where the web service and the html file with jQuery is located.
This is what my code looks like on JS –
—————————————
$.ajax({
url: “/myapp/Service.asmx/HelloWorld”,
contentType: “application/x-www-form-urlencoded”,
type: “POST”,
data: “name=Khan”,
success: function(msg)
{
document.getElementById(“result”).innerText = msg;
},
error: function(req, status, err)
{
document.getElementById(“result”).innerText = req.responseText;
}
});
———————————-
Everything here works just fine when I call the URL (url of the html file where jQuery is located) from the same machine where my webservice is. Then I go to a different machine and call the same exact URL, and nothing works.
Can someone please help? What am I missing? I tried the same thing with Prototype.js – again, everything works except when I go to a different machine.
Thanks very much.
Khan
I’m not sure how your machines are configured, but the URL to the service on a production machine is probably going to be /Service.asmx/HelloWorld, instead of /myapp/Service.asmx/HelloWorld.
Turns out everything was going in the right place – except that Web.Config file of my web service needed to be updated to be accessed from remote machine. Here is the solution in case if anyone else had the similar issue -
Disable the HttpGet, but keep the post. In that case, everything works great. This is a solution for the Dot Net 2.0 – I am not sure about the other versions of Dot Net though. Apparently by default Dot Net 2.0 disables the “HttpPost” and has to be added. This is why everything was working from the same machine where the web service and the javascript app was located, but would not work if i call the javascript app from a different machine.
Hope it helps others, who didn’t know like me :)
Khan
Hi Dave, sorry to worry u…I imagine u must be busy, but if possible, could u please assist me with the issue I am experiencing (my comment is just above Khan’s). Much appreciated!
Email me your code. I’m not sure I understand the problem you’re having.
Thanx Dave! I’ve just emailed you
I tried about code with VS2008, it didn’t work for me.
I even tried with complete URL of web the service still no luck.
In the debug mode, it didn’t come to web service code at all.
Can you help me to resolve my issue? I am not sure whats wrong I am doing here?
Thanks,
Raj
That’s too vague for me to give you much specific advice. A couple things I’d suggest are:
Double check that you don’t have any JavaScript errors on your page. One JavaScript error will abort execution of JavaScript on the rest of your page (like a single compilation error will in your code-behind).
Try running it in Firefox with the Firebug console open. This way, you can see if the service call is made at all and/or if the server is returning a 500 error.
I’m having trouble passing a parameter to my web method (parameter-less requests work fine). I am not sure why the server will not correctly parse the parameter, but as you can see from the response, it does not see the parameter.
I’ve boiled down my code to the bare minimum.
Server code:
Here is the javascript:
$(document).ready(function() { $.ajax({ type: "POST", url: "ReviewReader.asmx/GetReviewsByVanityUrl", data: "{'vanityUrl':'TEST'}", contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { $('#ReviewContent').removeClass('loading'); $('#ReviewContent').html(msg.d); } }); });And here is what the server response says:
{“Message”:”Invalid web service call, missing value for parameter: \u0027VanityUrl\u0027.”,”StackTrace”
:” at System.Web.Script.Services.WebServiceMethodData.CallMethod(Object target, IDictionary`2 parameters
)\r\n at System.Web.Script.Services.WebServiceMethodData.CallMethodFromRawParams(Object target, IDictionary
`2 parameters)\r\n at System.Web.Script.Services.RestHandler.InvokeMethod(HttpContext context, WebServiceMethodData
methodData, IDictionary`2 rawParams)\r\n at System.Web.Script.Services.RestHandler.ExecuteWebServiceCall
(HttpContext context, WebServiceMethodData methodData)”,”ExceptionType”:”System.InvalidOperationException”
Any thoughts, suggestions or ideas on what I am not doing correctly would be appreciated.
Thanks,
Dave
Please disregard, I just noticed the lower-case ‘v’ in my parameter I pass to the server, and now everything works.
jquery calling web method is working under .net 3.5 for me. However the same code does not work on .net 2.0. Can someone confirm the json data format is not support in .net 2.0? Or it handles differently in .net 2.0?
here is my code:
In ASP.NET 2.0, you need to have the ASP.NET AJAX Extensions 1.0 installed for this to work.
Also, the data will be returned without the “.d”.
Thanks for you comment Dave. i did have the ASP.NET AJAX Extension 1.0 installed. Does not seems like the jquery is calling the server side method. I have a debugger on and it’s never hit. The error message i got is 12031, status text is unknow..
That’s a network level error, not anything wrong with your jQuery or web service code. Make sure there aren’t any firewalls or “Internet security” software that could be interfering with the request.
The URL i used is codebhind of the page where the ajax call is being made..
It’s really behaving in-insistently. Sometimes i got the 12031 error, and sometimes i got the 200 error.
Any idea?
I resolved the issue. The problem i had was with the web config setting. Seems like i missed the version info on the ScriptModule.
Thank you for all for your help.
Dear Dave,
how should I handle with jQuery, response from web service, if need to pass to my js code few values?
Should I create two web methods or there is way how to get few values from one web method?
You can use a complex type: http://encosia.com/2009/04/07/using-complex-types-to-make-calling-services-less-complex/
Thanks for a great Article Dave. I am going to use your website as a reference for a long time to come!
I have a question. I am using jQuery Modal dialog to allow users to send messages. I am using this inside a user control. Some of the data values that I need to pass to the backend web service are bound to the user control as properties/attributes of the user control.
My question is, how do I access these user control properties from within the jQuery Ajax function and include them in the data block?
Thanks in advance.
You won’t be able to access any server-side properties of the user control on the client-side unless they’re rendered out as part of the user control’s markup. At the time that you’re manipulating it on the client-side, the user control doesn’t exist at all. It’s a purely server-side construct that only exists for a moment during the page life cycle.
If this information isn’t sensitive (or a security issue), you can embed it in the page through a hidden form element. Otherwise, having the user control store it in the Session is a good way to persist it until your jQuery callback.
Am able to get the code working however whenever the data returned is over 60kb the JS fails. Is there a limit on the amount of data that can be returned?
The default server-side limit is something like 2mb, but just in case its being set low somewhere else on your server, try using the maxJsonLength web.config setting:
Thank you for the wonderful article Dave. I’ve been a long-time admirer of the good work you’re doing at Encosia.
Subject – Call web service from remote machine
I am able to call local web service (from my machine only) using Jquery. Following is the code that works fine:
$.ajax({
type: “POST”,
url: “http://localhost/SampleWS/TestService.asmx/GetDetails”,
contentType: “application/json; charset=utf-8″,
data: paramList,
dataType: “json”,
success: successFn,
error: errorFn
});
But when i call web service from remote machine (With in my domain), I get “Permission Denied” exception(even I give my machine IP instead of “localhost”). for example i give “url” as follows:
url :”http://[REMOTEMACHINEIP]/SampleWS/TestService.asmx/GetDetails”
Then I get “Permission Denied” error.
Please help
Prashant –
Try this:
$.ajax({
type: “POST”,
url: “/SampleWS/TestService.asmx/GetDetails”,
contentType: “application/json; charset=utf-8″,
data: paramList,
dataType: “jsonâ€,
success: successFn,
error: errorFn
});
Hi Paul,
Good to see your reply. BUT the problem is – i need to call a web service that is deployed on some other machine. so i have to give complete url (With IP) instead of short url “url: “/SampleWS/TestService.asmx/GetDetails—.
I hope you would understand my problem now.
Parashant:
Note: All remote (not on the same domain) requests should be specified as GET when ‘script’ or ‘jsonp’ is the dataType (because it loads script using a DOM script tag). Ajax options that require an XMLHttpRequest object are not available for these requests. The complete and success functions are called on completion, but do not receive an XHR object; the beforeSend and dataFilter functions are not called.
Info on JSONP: http://bob.pythonmac.org/archives/2005/12/05/remote-json-jsonp/
Jquery.get http://docs.jquery.com/Ajax/jQuery.get#urldatacallbacktype
This should solve your problem. For security reasons you are not allowed to post data to a webservice on a different domain.
Great article, helped me getting started with jQuery Ajax and to replace MS Ajax Library for my web services.
There is one question i want to ask though,
When using MS Ajax, it abstract JSON completely and we can use defined classes in web service as a valid JS object… e.g
//class defined in web service
public Class exampleClass
{
public String xString;
public int count;
}
now we can access this in JS by just doing this when using MS Ajax
var exampleClassInstance= new exampleClass();
exampleClassInstance.xString=’blah blah’;
and with this we can call the function.
Now MS Ajax out of question after using jQuery $.Ajax calls. To send data we have to use something like this
var xString=”blah blah”;
$.ajax({
……
data: “{‘RecAppID’:{‘__type’:'exampleClass’,'xString’:'”+xString+”}}”,
……
});
even though its not a big thing but i just want to know what you think how we can do abstraction like MS Ajax on json call?
I’m not sure if it’s exactly what you’re asking, but you can clean up the “data” parameter by using a technique like this: http://encosia.com/2009/04/07/using-complex-types-to-make-calling-services-less-complex/
You pointed me to exact right article. So the conclusion is, we have to build our own technique to pass complex data type.
I did it will a little difference. When page load for the first time, it register json of all the classes i required in client side e.g
//required class
class a
{
public string b;
}
//////asp page load method////
protected string classAJson;
page_load(…)
{
if(!page.ispostback)
{
javascriptsearlizer js=new javascriptsearilizer();
classAJson=js.searlize(new a());
}
}
and in the client side i can do this.
var classAObject=eval(‘(‘+”+’)');
function usingASPobject()
{
classAObject.b=”some data”;
}
what do you think about this technique?
If you use an ASMX “ScriptService” (shown in this post) or a page method, there’s no need to manually serialize it on the server-side or deserialize it on the client-side. ASP.NET AJAX and jQuery will take care of all that for you.
thanks a lot dave for the great article, i am calling webservice using jquery, but after the function is return from the webservice all my controls (Dropdowns) in page stops postbacking data , it works in IE 7 but not in firefox 3.0,
have you faced like this problem before.
Thanks a lot! This was really helpful. I used it to asynchronously load different sections of a long report which took ages to load otherwise.
HI Dave, great article! I used it and works fine in IE, but in FireFox i’m getting HTTP Error 400 Bad Request
this is my code, can u help me? Thanks in advance.
HTML:
$.ajax({ type: “POST”,
url: “../../../../JsonServices.asmx/GetNews”,
data: “{CategoryId:” + cat + “}”,
contentType: “application/json; charset=utf-8″,
dataType: “json”,
success: function(response) {
mycarousel_itemAddCallback(carousel, carousel.first, carousel.last, response);
},
failure: function(msg) {
$(‘#output’).text(msg);
}
});
WebService:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
// To allow this Web Service to be called from script, using ASP.NET AJAX, uncomment the following line.
[System.Web.Script.Services.ScriptService]
public class JsonServices : System.Web.Services.WebService
{
….
[WebMethod]
public List GetNews(int CategoryId)
{
try
{
DataSet DS = null;
if (CategoryId != 0)
{
NetTiersProvider dataProvider = ConnectionScope.Current.DataProvider;
DS = dataProvider.ExecuteDataSet(System.Data.CommandType.Text, “Select * from vw_AdsResume where CategoryId = ” + CategoryId);
}
List L = new List();
foreach (DataRow R in DS.Tables[0].Rows)
{
String TitleText = R["Title"].ToString().ToLower();
String Price = R["Moneda"].ToString() + ” ” + R["Price"].ToString().Replace(“,00″, “”).Replace(“.00″, “”);
…..
…..
News N = new News(TitleText, R["Id"].ToString(), imagead, imageagency, Price, HRef);
L.Add(N);
}
return L;
}
catch (Exception ex)
{
Trace.Write(ex.ToString());
return null;
}
}
….
public class News
{
….
String id;
public String Id
{
…
I don’t immediately see anything wrong with that. I’d suggest watching it in Firebug’s “net” tab and look for anything obviously wrong with the URL that’s being requested. Try copying it from Firebug and accessing it directly in the browser too.
Nice tutorial, very helpful. Thanks
Hi Dave,
Would you recommend asp.net development with html server controls and jquery without using any server controls of asp.net . so that there are no viewstates and asp.net is used mostly for its infrastructure such as security, .net framework , role provider etc.
That is primarily how I’ve been using ASP.NET for the past year or more. I’ve been very happy with the results, and would definitely recommend it.
At the same time, I do still use TextBoxes and Buttons for posting forms to the server traditionally, and a Repeater or ListView is often useful. I completely avoid the heavy controls like the GridView though.
Hello Dave,
I hope you can help me.
I think I’m having this cross-domain issue (although I haven’t tried it yet on production, the issue persist in development).
I have two projects running on the same machine, one project (PRJ_1) has the webservice, which uses the default HelloWord method, and the other project (PROJ_2) needs to access PRJ_1′s webservice, but I’m getting this error, “Request format is unrecognized for URL unexpectedly ending in ‘/HelloWorld/’. ”
PRJ_2 uses jQuery to fetch PRJ_1′s webservice.
This is PRJ_2 page that uses jQuery.
Result from webservice must reside here.
—-
This is PRJ_1 webservice.
As you can see, PRJ_1 webservice data information isn’t sensitive (no need for authentication), this is just like how I wanted it, anyone can access real data through a webservice.
How can I go on with this? Thank You for your help Dave!
-imperialx
Is project 2′s address also localhost:8008 or is it using a different port? Changing the port does run afoul of the cross domain restriction.
Hello Dave,
Project 2 has different port. So this is cross-domain restriction, but how could I use my webservice on a different port/domain? Will jQuery helps prevent cross-domain issue?
Hello Dave,
I can get the response/html viewable from Firebug when I don’t directly call the webservice (.asmx) but calling the page instead (.ASPX) using jQuery.getJSON, however, I couldn’t pass the result to a page element (e.g. div).
This is what i mean,
Below is PRJ_2 jQuery that calls PRJ_1 homepage (PRJ_1_Index.aspx).
$(document).ready(function() { $.getJSON("http://localhost:8008/PRJ_1/PRJ_1_Index.aspx/&callback=?", function(data) { jQuery('#resultDIV').html(data); }); });Using Firebug, and looking at RESPONSE and HTML tab, I can see my desired output but I couldn’t pass the output to my page element ‘resultDIV’. The elemnent remains blank. I’m not getting any error cause the status is ’200 OK’.
This is PRJ_1 page and code-behind. PRJ_1 code-behind calls the webservice directly and pass the result to its page. I use the default HelloWorld method when creating the webservice file.
I hope you can help me Dave.
-imperialx
When you specify a cross-domain URL to $.getJSON, it switches to JSONP. That’s why it’s appearing to work. JSONP is totally different though.
Will these projects eventually be hosted on the same domain and same port, in separate virtual directories?
No, it will not. Both will be hosted on separate domain and hosting accounts, one will be hosted at GoDaddy while the other at SoftSys.
Can I still use jQuery with cross-domain?
The cross-domain restriction isn’t a jQuery issue, but a restriction of the browsers’ XMLHttpRequest objects. Imagine if you visited ModeratelyTrustedSite.com and it could immediately fire off asynchronous background requests to YourBank.com, sending the cookies and/or authentication information your browser had stored for that domain.
Either look into JSONP (which jQuery does support) for a way to bridge the cross-domain gap, or consider using a service on the consuming domain to act as a proxy (which is what the RSS requesting service effectively does in this example) since server-side code doesn’t have the cross-domain restriction.
Just didi webservice method request, return simple string “Hello World” (JSON response “{“d” : “Hello World”}”).
When i use JQ 1.3.2 it works ok, but in 1.4.1 throw error:
- afeter POST is succes i get to line:
* httpData: function( xhr, type, s ) { *
and then to line:
* data = jQuery.parseJSON( data ); * from where we go to function parseJSON, where type variable is ‘undefined’ and there after some RegEx we get to line:
* jQuery.error( “Invalid JSON: ” + data ); *
Where data=Hello World”, because i use dataFilter in $.ajaxSetup:
* if (msg.hasOwnProperty(‘d’))
return msg.d;
else
return msg; *
I did some fix in JQ 1.4.1 and it is ok
Best Regards,
Goran Milosavljevic.
Thnx for response.
Thanks for helping us cut out the bloat of the ASP.NET client side AJAX framework.
Amazing to see you’re still responding to comments on this post – and relieving as I have a problem also:
I am trying to setup a webservice as per some of your examples, however, when returning type IEnumerable the method is never included in the webservice:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class QuestionnaireService : System.Web.Services.WebService
{
[WebMethod]
public static IEnumerable GetCandidates()
{
// cool stuff
}
}
however if I return primitive types it shows up fine. From your examples (RSS reader specifically) you appear to use IEnumerable so is there something I’m missing?
Many Thanks,
Dan
The GetCandidates method shouldn’t be declared as static.
After being stuck on that all night, as soon as I posted this I realised the method was marked static (teach me to copy and paste from a page webmethod to a webservice).
However I’m now getting an error about IEnumerable not being serializable?
ASMX’s XML serializer doesn’t handle IEnumerable. You’ll have to be sure that you’re jumping through all the right hoops (described in this post) to get a JSON response. That also means that you can’t test it by hitting QuestionnaireService.asmx directly in your browser.
It’s probably worth noting that you can also return a typed collection, like List<Candidate>. Unless you need the flexibility of IEnumerable, the strongly typed collection may be easier to work with.
Thanks for you patience on this, I believe i am jumping the hoops but the response always seems to be :
Content-Type text/plain; charset=utf-8
which i think should be application/json; charset=utf-8
my jquery request:
$(document).ready(function() {
$.ajax({
type: “POST”,
contentType: “application/json; charset=utf-8″,
url: “MyService.asmx/GetCandidates”,
data: “{}”,
dataType: “json”,
success: function(msg) {
$(“#feedback”).html(msg.d);
},
error:function (xhr, ajaxOptions, thrownError){
$(“#feedback”).html(xhr.responseText);
}
});
}
Is there something I need to do in the webservice itself or in the web.config to ensure the correct response type?
Apologies for posting here, if there is somewhere more appropriate please let me know and I’ll stop cluttering your comments :)
Another hour on stack overflow (reading your responses) and googling (leading me to your recent posts) has finally got me sorted. The final stumbling block was my PublicKey for System.Web.Extensions was different, once I found that everything has clicked into place.
Thanks for all your efforts Dave, to where do I send the beer?
Glad to hear you got it figured out. I hadn’t considered the config being the issue since it was working for some return types. That one’s new to me.
Hi all,
I am getting Permission denied error on IE while accessing URL remotely
Any answer.
Thanks
Kunal
Hi am using Webservice as a different project and when i add a webreference of this in my project. then jquery call does not works. if the asmx file is in the same webapplication project then it works fine. Is there any way to cosume the webservice’s webmethod by puting the web reference of weservice.
XMLHttpRequest prevents cross-domain calls for security reasons. Different subdomains and ports count against this restriction as well. So, if you have an ASP.NET project running at localhost:1234 and a separate web service project running at localhost:5678, your calls won’t work.
If the service will eventually run in a separate virtual directory within the same domain, that will work when deployed. You can use IIS to test that locally (using the same configuration that keeps the domain identical).
Thanks Dave,
Now i put one folder in the same project inside that i put myServices.asmx file and inside that i am calling my referenced services web methods. Now it is working fine.
Finally, i am creating one wrapper webservice which is in my same project and from that i am consuming other webservices.
How to consume ASP.NET JSON Webservice for Google Ghrome? This example success to IE, But failed to Google Ghrome. Please reply me, Thanks!
–Rocky
This works in all the major browsers (including Chrome). jQuery’s $.ajax() abstracts away the cross-browser issues pretty well.
Is it possible to do this in a classic asp application? We have a huge intranet classic asp site (no .NET involded) that needs to access a map feature provided through a third party web service. The third party only provided an example for IE8, including a htc file.
thanks in advance,
Axel
jQuery itself is server-side-platform agnostic. If your third party service supports JSONP, you can use jQuery to directly call it pretty easily (see the relevant bits of the $.ajax() docs for details).
You can see an example of using jQuery to make a JSONP call on my site, actually. Take a look at how http://encosia.com/blog/includes/encosia.js uses JSONP to make a cross-domain call to Twitter for my latest status updates.
If your third party service doesn’t support JSONP, you’ll need to set up a server-side proxy to bridge the cross-domain restriction for you. That’s essentially what the ASMX service in this post’s example does.
Would this solution also work while calling a HTTPS web service using $ajax?
Or is there a trick to doing so?
As long as the document making the request and the service are both served via HTTPS and the service isn’t cross-domain, $.ajax() will work against HTTPS exactly the same way as with HTTP. I believe some browsers treat HTTP < -> HTTPS as cross-domain, similar to different ports on the same domain, which can cause trouble if you’re trying to access an HTTPS service from a page that was served via HTTP. So, that’s the main thing to watch out for.
Hi Dave – great article and site I have to say, getting plenty of ideas from it. One thing I’m not sure about is passing complex objects into a WCF service using jQuery/JSON. I have a WCF service and all the operations are receiving and returning message contracts (I’m using the Web Service Software Factory). When I add a service reference to the WCF endpoint all the objects get created for me in the proxy on the server side, but how can I create these objects on the client side with jQuery/JSON?
TIA,
Ciaran.
When you pass data in to WCF or ASMX, server-side objects and collections correspond to JavaScript objects and arrays. So, if you have a List, you can accept that as your input parameter type on the server-side, then feed it a JavaScript array that matches (e.g. [{prop1: 'value1', prop2: 'value1'},{prop1: 'value2', prop2: 'value2'}]).
I wrote a later post that goes into more detail about that and shows how you can automate it a bit: http://encosia.com/2009/04/07/using-complex-types-to-make-calling-services-less-complex/
Since you’re using WCF, one thing you have to watch out for is that it does not deserialize some input types quite as flexibly as ASMX. For example, you can pass ASMX a string for a DateTime, like “12/6/2010″, and it will DateTime.Parse that for you. WCF rejects it. Similarly, ASMX will accept an enum type’s string value, but WCF will only accept its underlying ID. If you run into trouble figuring out how to send something to the server, the easiest way to figure out what it expects is to return a sample value of that type from the server and inspect the JSON response in Firebug. If you mimic what it returns, you’ll be sending the right thing.
Nice one Dave good to know..Ciaran
i’ve one problem because when i make a call with type:GET to my asmx webservice i always get the response in XML format.
this is my example:
_ _ Public Function obtenerPendientesCompletoDeEmpleadoEnFechaParaArbol(ByVal matricula As String, ByVal fecha As String) As String Dim salida As String = "" Dim proxyws As ProxyDorletDatos.DorletDatos = Nothing Try proxyws = inicializarConexionServicioWeb(proxyws) Catch ex As System.Exception Throw ex End Try Dim DateFecha As Date Try DateFecha = crearObjetoFechaAPartirDeFechaDorlet(fecha) Catch ex As Exception Throw New Exception("El formato de las fechas no es valido") End Try Try Dim lstInfracciones As List(Of ProxyDorletDatos.pendienteCompleto) = proxyws.pendientesCompleto_obtenerInfraccionesDeEmpleadoEnFecha(matricula, DateFecha).ToList For Each infraccion As ProxyDorletDatos.pendienteCompleto In lstInfracciones salida += "[{ ""data"" : """ & infraccion.tipo & "|" & infraccion.clase & """, ""children"" : [ { ""data"" : ""Un hijo"", ""state"" : ""closed"" } ], ""state"" : ""open"" }," Next salida = salida.Substring(0, salida.Length - 1) salida += "]" Catch ex As Exception End Try Return salida End FunctionAny idea??
Thanks
this code is located before the function:
_
_
one more time:
[ScriptMethod(ResponseFormat:=Script.Services.ResponseFormat.Json, UseHttpGet:=True, xmlSerializeString:=False)>] _
[WebMethod()] _
You need to use a POST request (with the application/json content-type) to avoid XML.
Also, you shouldn’t build your own JSON string in the method. The ASP.NET ScriptService will automatically serialize your return value as JSON. So, if you just set the return type to
List(Of T)and return a value of that type in the method, it will automatically be JSON serialized (just like how those WebMethods traditionally XML serialize their return values).In addition to above suggested WebMethod attribute and other attributes, also check that in your web.config file all the ajax handlers are present or not. If possible create any ajax application an take the web.config file of that ajax application into your application.
thanks for your answer
i can´t use POST in this case, because i´m using a jquey plugin that uses GET. Finally i used one ashx. The ashx can recieve GET and answer with JSON.
Hi,
I have auto suggest text box and when I give some input, the suggestions are listed as “undefined”.
Can you please help me with this
Thanks.
Just a question I am new to jQuery. I am seeing examples on the web when making an ajax call to a web service they using failure: callback. I look at jQuery documentation and can’t find it. Shouldn’t it be error: not failure ?
You’re right. When you’re using jQuery, any failures will be raised in $.ajax()’s
errorcallback. It doesn’t support any events named failure.Great article for my future project with webservices.
Great. This is exactly what I needed. Thanks!
Thanks Mate !!!
Hi there Dave,
Thx for your great posts.
As quite a newcomer to JQuery and JSON I got your example working but can’t seem to get any data when using the example coupled with a masterpage!
No visible errors just the loader and no data.
Any suggestions?
Axl
If it broke when you moved it to a master past, the problem is probably ASP.NET rendering something with a ClientID that you don’t expect. So, the jQuery code that hides the loader isn’t able to find the div to remove the loading class from it.
See this post for more information and some strategies for dealing with that (be sure to read the comments too): http://encosia.com/2007/08/08/robust-aspnet-control-referencing-in-javascript/
Hi, Dave
I get error “A circular reference was detected while serializing an object of type” for return POCO class generated from Entities Data Model as JSON. How can i solve it ?
Consider using a simple view model (aka DTO) with only the data you really need for your client-side app, using AutoMapper to project your EF object into that simpler class, and then returning that instead of the full EF object.
Hi, Dave.
Could you give me some example of using AutoMapper, i have no used it before. thanks
There are lots of examples online in blog posts and on Stack Overflow. If you Google around a bit, you shouldn’t have any trouble finding good examples.
hey dave, excellent article thanks!
i have one query, i want to consume a web service which has certificate based security. is it possible to use the browser certificate store to consume such a service
thanks,
sharjeel
You can secure AJAX requests the same as regular, full-page requests. If you load a page via HTTPS and then make a relative path AJAX request, it’s automatically going to be a secured request.
Hello Dave,
Thanks for the great article and the extra article links. I have been struggling on this for a long time (have done thousands of google search but no result) and I’m not even sure if this is possible maybe you can help me on this.
What I’m trying to do is call ASMX service from JQuery. If the ASMX service code is within the project I can access the Service Methods by directly referencing it (e.g. url: “/service/HelloWorld.asmx/Helloworld” I’ve done this before in a project”. But now I want to put some of the reusable services (code) in a separate project and host it on IIS. But as soon as I host it on IIS 7.5 and try to invoke the service method from AJAX it fails. The server where it’s hosted is under the same domain. Do you think this is possible, from what I’ve read in many articles I’ve found that they talk about cross domain access for webservices and it’s not possible. Please guide me on this, your help would be greatly appreciated and it will help me save a lot of time.
Thanks
Mani