Using jQuery to directly call ASP.NET AJAX page methods
AJAX, ASP.NET, JavaScript, jQuery By Dave Ward on May 29th, 2008When it comes to lightweight client-side communication, I’ve noticed that many of you prefer ASP.NET AJAX’s page methods to full ASMX web services. In fact, page methods came up in the very first comment on my article about using jQuery to consume ASMX web services.
Given their popularity, I’d like to give them their due attention. As a result of Justin‘s question in those comments, I discovered that you can call page methods via jQuery. In fact, it turns out that you can even do it without involving the ScriptManager at all.
In this post, I will clarify exactly what is and isn’t necessary in order to use page methods. Then, I’ll show you how to use jQuery to call a page method without using the ScriptManager.
Creating a page method for testing purposes.
Writing a page method is easy. They must be declared as static, and they must be decorated with the [WebMethod] attribute. Beyond that, ASP.NET AJAX takes care of the rest on the server side.
This will be our page method for the example:
public partial class _Default : Page { [WebMethod] public static string GetDate() { return DateTime.Now.ToString(); } }
What about the ScriptManager and EnablePageMethods?
Traditionally, one of your first steps when utilizing page methods is to set the ScriptManager’s EnablePageMethods property to true.
Luckily, that property is a bit of a misnomer. It doesn’t enable page methods at all, but simply generates an inline JavaScript proxy for all of the appropriate methods in your page’s code-behind.
For example, if a ScriptManager is added to the above example’s corresponding Default.aspx and its EnablePageMethods property is set to true, this JavaScript will be injected into the page:
var PageMethods = function() { PageMethods.initializeBase(this); this._timeout = 0; this._userContext = null; this._succeeded = null; this._failed = null; } PageMethods.prototype = { _get_path:function() { var p = this.get_path(); if (p) return p; else return PageMethods._staticInstance.get_path();}, GetDate:function(succeededCallback, failedCallback, userContext) { return this._invoke(this._get_path(), 'GetDate',false,{}, succeededCallback,failedCallback,userContext); }} PageMethods.registerClass('PageMethods',Sys.Net.WebServiceProxy); PageMethods._staticInstance = new PageMethods(); // Generic initialization code omitted for brevity. PageMethods.set_path("/jQuery-Page-Method/Default.aspx"); PageMethods.GetDate = function(onSuccess,onFailed,userContext) { PageMethods._staticInstance.GetDate(onSuccess,onFailed,userContext); }
Don’t worry if you don’t understand this code. You don’t need to understand how it works. Just understand that this JavaScript proxy is what allows you to call page methods via the PageMethods.MethodName syntax.
The important takeaway here is that the PageMethods proxy object boils down to a fancy wrapper for a regular ASP.NET service call.
Calling the page method with jQuery instead.
Knowing that a page method is consumed in the same way as a web service, consuming it with jQuery isn’t difficult. For more detailed information, see my previous article about making jQuery work with ASP.NET AJAX’s JSON serialized web services.
Using the jQuery.ajax method, this is all there is to it:
$.ajax({ type: "POST", url: "PageName.aspx/MethodName", data: "{}", contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { // Do something interesting here. } });
Putting it all together.
Corresponding to the example page method above, here’s our Default.aspx:
<html> <head> <title>Calling a page method with jQuery</title> <script type="text/javascript" src="jquery-1.2.6.min.js"></script> <script type="text/javascript" src="Default.js"></script> </head> <body> <div id="Result">Click here for the time.</div> </body> </html>
As you can see, there’s no ScriptManager required, much less EnablePageMethods.
As referenced in Default.aspx, this is Default.js:
$(document).ready(function() { // Add the page method call as an onclick handler for the div. $("#Result").click(function() { $.ajax({ type: "POST", url: "Default.aspx/GetDate", data: "{}", contentType: "application/json; charset=utf-8", dataType: "json", success: function(msg) { // Replace the div's content with the page method's return. $("#Result").text(msg.d); } }); }); });
The end result is that when our result div is clicked, jQuery makes an AJAX call to the GetDate page method and replaces the div’s text with its result.
If you’re wondering about the msg.d, be sure to see my post about what it is, why it’s there, and why you may not need it in your version of ASP.NET: A breaking change between versions of ASP.NET AJAX
Conclusion
Page methods are much more openly accessible than it may seem at first. The relative unimportance of EnablePageMethods is a nice surprise.
To demonstrate the mechanism with minimal complications, this example has purposely been a minimal one. If you’d like to see a real-world example, take a look at Moses’ great example of using this technique to implement a master-detail drill down in a GridView.
If you’re already using the ScriptManager for other purposes, there’s no harm in using its JavaScript proxy to call your page methods. However, if you aren’t using a ScriptManager or have already included jQuery on your page, I think it makes sense to use the more efficient jQuery method.
Get the source
If you’d like to browse through a complete working example of what’s been covered in this post, take a look at the companion project at GitHub. Or, if you’d like to download the entire project and run it in Visual Studio to see it in action yourself, grab the ZIP archive.
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.
26 Mentions Elsewhere
- Weekly Web Nuggets #14 : Code Monkey Labs
- Acceder a PageMethods con jQuery - Variable not found en Geeks.ms
- Weekly Links: ASP.NET MVC, .NET, ADO.NET Data Services, Silverlight, WPF… | Code-Inside Blog International
- Eye On .Net - episode 3 - Hisham Elbreky
- Good links: ASP .NET and JQuery - Programmatically Speaking ...
- Using jQuery to Consume ASP.NET « vincenthome’s Software Development
- .Net Discoveries : A Better ASP.Net Member/Role Management Page Pt. 7
- JQuery Articles
- links for 2009-05-28 « Minesa IT
- Getting to Grips with Form Submission using jQuery .ajax() - My Tech World
- jQuery and AJAX « Blonde Model's Blog
- Resurrection « ActiveEngine
- BinzBlog » Unit Testing Javascript
- Proposed Workshop schedule – jQuery « Carlos Guarany – from Toronto
- I can always change it later » Blog Archive » DotNetNuke + Custom WebMethod + jQuery - Coasting the life of a .NET dev.
- What is Page Method and How to use it « Hadjloo's Daily Notes
- 在ASP.net中前台js中怎么样调用后台的方法!急需解决,求各位大侠帮忙!!! - .net常见问题 - 在ASP net中前台js中怎么样调用后台 方法 急需解决 求各位大侠帮忙 .NET技术 ASP.NET - 123Doing
- Cross-Domain, Ajax Fundamental understanding « Peak bytes
- Website Log Tail « Wibber's Blog
- Imitate Click using HttpWebRequest
- 在ASP.net中前台js中怎么样调用后台的方法!急需解决,求各位大侠帮忙!!! - .net常见问题 - [标签:tags] - 开源网 | 123Doing
- ASP.NET JQuery AJAX « Code Kat ^..^
- evitareri caricamento pagina al click su bottone - ASP 3.0, ASP .Net - MasterDrive.it
- Communicating with Code Behind using jQuery Ajax | Progressive Data Systems
- Using jQuery to directly call ASP.NET AJAX page methods « Derek Reynolds – Brain Dump-O-Matic
- [WebMethod]‘s and jQuery « Mike#



Nice article Dave, going to play around with this and see where its limits are.
Hi, How I can pass parameters using this method?
For Example with this function:
You can add a data parameter to the $.ajax call. You’ll find some examples in the comments on the previous post about calling web services with jQuery.
You can find the official documentation on $.ajax here: http://docs.jquery.com/Ajax/jQuery.ajax#options
I’m getting the same error Moses has a note on in his blog entry, where the “Content-Length” header is not being sent by Firefox 2.0.0.14. The exact error response is “Length Required”. His fix was to add the xhr.setRequestHeader(“Content-Length”, 0); type line to the beforeSend() function, but this still does not work for me – the header is not being sent according to Firebug. IE6/IE7/Opera/Safari work fine… tried with jQuery 1.2.6 and 1.2.3. Anyone else?
Erm, after an hour of scratching my head, I found the solution. I had to specify: data: “” in my $.ajax() call. Passing null or leaving that parameter out causes Firefox to leave out the content-length header. Hope this saves someone else some time.
Interesting. Thanks for the update, Ryan.
What server environment were you getting that error from? I’ve tested with Cassini and IIS7 with no trouble. I’d like to narrow down what circumstances the content-length becomes a problem in.
IIS6 on Windows Server 2003. That is interesting… I also tested with both Cassini and IIS5.1 and they didn’t have a problem.
Check out these links: http://forums.iis.net/p/1119456/1744358.aspx
http://objectmix.com/inetserver/284636-windows-2003-iis-server-not-responding-correctly-post.html
They seem to indicate that neither IIS6 or 7 would work without the Content-Length header unless the Transfer-Encoding: chunked header was present. Did you have that in your IIS7 test?
After testing across more server types, it looks like the best usage is this:
Since there’s POST data now, manually setting the content-type isn’t necessary. So, I think that’s cleaner anyway.
I’m going to update the two applicable posts to reflect that usage. Thanks for the feedback, Ryan.
Excellent article. I started to play with jQuery recently and I am very interesting in how to integrate it with ASP.NET. And this is more than useful!
Man, this is a great approach since ASP.NET AJAX and it’s poor performance isn’t a viable solution for many sites.
Great technique, but I don’t currently have the liberty to add in another library like JQuery. Currently I only have the .Net Ajax library. Could you please transalate this method into using the Sys.Net.WebRequest Class of the Ajax library (http://msdn.microsoft.com/en-us/library/bb310979.aspx)?
If you already have a ScriptManager on the page, you could use the EnablePageMethods property to generate the JavaScript proxy. There’s no need to manually call the page method with WebRequest in that scenario.
Thanks, but actually I originally had PageMethods js syntax for the calls….worked great, but our framework requires a level of authentication in an HTTP module that checks a GUID in either the Request.QueryString or Request.Forms.
I delved into behind-the-scenes proxy code generated, but the GUID in the querystring is gone(url is filename.aspx/GetMethod. It seems that the abstraction resulting from the proxy code of PageMethods has taken away the ability for me to get it in there, at least from what I can see so far. I believe it was said that the proxy code makes 3 calls..??
Update: works in small app with js sitting on same .aspx file, but not on real app with js in dif directory. Would this matter?
Works (small app):
Doesn’t hit (code-behind):
Sorry about being verbose. Thanks again.
Try an absolute path for set_url(), to make sure the location of your js include isn’t causing trouble.
Also, I’m assuming it is in your code, but make sure that last line of the non-working js is:
What you posted is missing the parens.
Other than that, are you getting any JavaScript errors at all, or is it failing silently?
Yes! It was missing the parens… funny the browser would just run through the code past it as if nothing was wrong, no syntax error. Here is my complete solution for anyone else it might help. It makes uses of Asp .Net Ajax library versus JQuery.
Thanks again for your help, love these articles.
Does this work with ASP.NET 2.0. Been trying to get it working but having a bit of a hard time.
As long as you have the ASP.NET AJAX extensions installed, yes.
I found the problem….apparently i can’t have a static method called test. Just doesn’t work. Test works but all lower does not work and returns a ‘parsererror’ error. Weird. very weird. Any ideas??
Not sure about that one. I’m able to declare this:
Without any errors.
How about clientcallback from Jquery implementing Icallbackeventhandler, that way we can use it on controls!!!.
The problem I have with ICallback is that it sends the ViewState in the callback. At that point, you’re almost back to the inefficiency of the UpdatePanel.
This was all working great for me, until today :(
Unfortunately, it all seems to fall down under Firefox 3, and I am having one heck of a time trying to find out why :(
Hey Dave, I I have a question, Someone asked me about this:
In my sample I just uset $(…).html(msg); while us use $(…).html(msg.d);
My sample works fine, and your sample too, But the guy told me that mind didn’t work for him, and when her replaced msg with msg.d as in your sample it worked fine!
Could you please clarify to what does “d” refers to! because I review the jQuery.Ajax Documentation for success and failure handlers and reached nothing.
Thank you Dave
The reason for the difference is that the “d” was added in ASP.NET 3.5. Running the same piece of code on 2.0 and 3.5, you’ll get the straight return in 2.0 and the “.d” type return in 3.5.
It’s my understanding that the reason for this is that forcing the result into a JSON array helps prevent potential XSS attacks.
I am using VB.NET and I cannot access my wet method. I tried making my method Public, Shared and no luck. Any
Suggestions for us VB.NET guys (I hope not to get bashed here)?
The VB equivalent should be something like this:
Wow, I just re-read my post from yesterday “I am using VB.NET and I cannot access my wet method…”. Wet Method? Hilarious! Thanks Dave, that worked perfectly. Loving JQuery!
Wow, I just re-read my post from yesterday “I am using VB.NET and I cannot access my wet method…”. Wet Method? Hilarious! Thanks Dave, that worked perfectly. Loving JQuery!
Hi Victor, I have the same previous problem. but i can not fix it,
Can you show me detail about the way to call a function on server side throught ajax like that.
Can you help me!
Alex
Hi,
I can not make webmethod call with jquery work in vb.net. If do the same thing from c# it works fine. been pulling my hair. help me.
here’s my vb webmethod
here’s my javascript
and here is my HTML
it just doesnot work in vb. am i missing anything. help me
What’s it actually doing? Are the contents of the div changing at all?
I’d take a look at it in FireBug’s console and check out the request and response.
hey dave,
nope the content is not changing at all.
have FF3 and wont support firebug. but i checked the response from fiddler, it shows the whole page.
any idea why it is doing that?
FireBug 1.2 works on FireFox 3.
In my experience, what you’re seeing usually happens when the content type isn’t correct or the request isn’t a POST. I see that’s correct in your jQuery call, but double check all the specifics of the request headers in FireBug.
well i figured out what the problem was. had nothing to do with vb.net or jquery. i thought if not jquery, lemme try that with scriptmanager, but couldnt get scriptmanager on the page. turns out the .net 2.0 site i was working on was not ajax enabled. made it ajax enabled site and BAM!!! everything back to normal.
sometimes what you think the culprit is may not be the real culprit. :)
ohh in .net 2.0 msg.d wont work. it;s just msg
btw love your articles. keep on the good work.
thanks
Thanks for your help. And here is how you make web site “AJAX Enabled”
Once, I have done this step, call back are working like charm
Can’t thank you enough for this. Been wanting to punch through my computer screen.
OMG thanks you so much, you save my life ;)
i change msg.d with msg and BOOMM!! Thanks!
I’ve just found that this method will only work if you’re PageMethods are in code-behind, it doesn’t work when they are part of the aspx.
ASP.NET AJAX PageMethods however, work in both.
Dave,
Thanks for posting this, it got me started on what I was trying to do.
My next task is somehow generating a proxy script for these webmethods, but uses the jquery ajax functions rather than asp.net ajax. Any ideas on how to do this?
Thanks!
Just a quick question because I couldn’t think of a better place to post this….
We’ve been using ashx handlers on the server side to supply jQuery with JSON formatted data for some time. Everybody else seems to use page methods which I assumed would have an extra overhead.
I must be wrong but can anybody explain why page methods (or even web services) are more suited to this than a handler?
I’m not aware of specific data on how their performance compares, but I think all three are probably very similar. Maybe some heavy testing is in order.
For me, one nice thing about web services and page methods is that they automatically handle the JSON serialization.
It would be interesting to know if anybody has done that actually.
I assume (from my very limited asp.net knowledge) that a .aspx page would have the extra overhead of the page life cycle (init, preinit etc.) whereas an http handler doesn’t need to do any of that?
I do know that the Page isn’t fully instantiated for a page method call (if at all). For all intents and purposes, page method calls are identical to web service calls. I haven’t noticed any performance differences between those two at all.
Page methods definitely don’t have the overhead of something like a partial postback, where the entire Page is re-instantiated.
I might run some tests and make a post of it sometime soon. It would be good to know for sure.
Hey Dave! Nice article, I’ve been benefitting from alot of your jQuery posts lately. I recently decided it was time to start looking into jQuery and thus far I totally love it. It’s concise and makes the ASP.NET AJAX framework seem so bloated and obliquitous.
Anyways, I’ve been having some problems with making POSTS from jQuery to an ASP.NET page. I am unable to retrieve the data from the Request.Params collection in my Page_Load code-behind. I have a .aspx page that has a main task of sending emails programmatically. I want to be able to POST to this page from a contact form on another page via jQuery (the plan is to have a brief contact form on every single page, and a bigger contact form on this main contact page where they can attach files to the message as well [which is why I am posting to a page instead of a handler]). I will get to the big contact form later, but first I need the small forms to work. If I change my JS to use the GET method, it works perfectly. But I’m going to need to make POST work for the file uploads. Is there anything obvious I am missing here? I am using the jQuery Ajax serialize() function to transform the user input into legitimate POST parameters, but I can not seem to receive any of the data on the server-side.
Getting frustrated. Hope you can help!
I like your blog, by the way.
Best regards…
I have used jQuery and Ajax for my site and it works great. I had a look at dojo but jQuery is I think sampler and easier. I like the integration with flash too.
Great post thanks.
I’m looking to switch from Ajax.NET Pro to jQuery and this solution helps. However, I have quite a few helper classes in my App_Code folder that provide methods for Ajax calls. How would they be referenced in the jQuery.ajax url parameter when there is no .aspx page?
I also have custom controls that are compiled separately and included in the project. How would methods in the control DLL be referenced?
I’m not aware of any way to directly access arbitrary methods and properties of classes that aren’t exposed by a page method or web service. The usual solution is to create web services to act as proxy to that business logic.
The methods are not arbitrary. I do expose the methods with a [WebMethod] attribute but it is in a compiled DLL, not a page. Every reference I see mentioned here describes calling Page.aspx/method whereas I need something like MyDll.dll/method including the proper namespace.
I don’t think adding a [WebMethod] attribute to a method in a class library does anything.
Possibly not — I have yet to try it. Ajax.NET Pro does allow this and, since it has been “discontinued”, I need a viable replacement. If you can’t do it this way, how would you create a distributable web control that uses jQuery and Ajax? For example, let’s say you create a generic list control that would use Ajax to filter the data on the server side (for argument’s sake, with simple SQL and no business object). Would you require someone using this control to create a separate web service as opposed to just adding the compiled DLL to their project? I’m sure this must exist — I just don’t know how to do it.
Bundling AJAX functionality into an assembly is actually problematic in the current system. That’s why you have to edit in the HttpHandler’s web.config setting for ASP.NET AJAX and it’s why you have to create a separate ASMX when using the AutoComplete Extender.
I don’t know of a fully encapsulated way to redistribute that sort of functionality, currently. If you find a way, I’d love to hear about it.
Can you point me to a site that describes how to do with with the HttpHandler? I’d like to do exactly what RobbS is describing but I’ll take having to implement a handler in the mean time, just looking for a guide to do so.
Thanks,
Jeff
There’s a great example of doing that in Advanced ASP.NET AJAX Server Controls.
I don’t remember any particular articles online that went into detail about using an HttpHandler in a server control, but it’s basically the same as using an HttpHandler normally. So, any tutorial you Google up should be helpful.
Hi,
Do you know how/if possible to get the message from an exception thrown in the called PageMethod? I hook up to jquery’s error function, but the message I get is “error”, instead of the actual exception message thrown server-side.
If this were your jQuery.ajax() error handler definition:
xhr.responseText would contain the error details thrown on the server side.
Thanks for the well-written and concise explanation!
This is the solution I would like to implement, and for the most part, it works well.
My problem, though is that WebMethods that do not reside on the Default.aspx page are not recognized or callable. When I add a line like:
ajax(“Services.aspx/getServices”, {}…
I get an error including this line (Viewer is the project folder):
Requested URL: /Viewer/Default.aspx/Services.aspx/getServices
Obviously, this isn’t right. Any idea why it would prepend “/Viewer/Default.aspx” into the URL?
Thanks!
Are you using any sort of URL rewriting in the site?
If not, post your exact $.ajax() call, so I can take a look at it.
Nope, no URL rewriting.
The page is called Services.aspx. The code-behind where the WebMethod resides is Services.aspx.cs, and it’s in the root folder of the web project.
Here’s the ajax call:
ajax(“Services.aspx/getServices”, {}, function(result) {
var services = JSON.parse(result.d);
$(‘#contents’).html(createServiceList(services));
});
I think some of your code is getting filtered out. Make sure you post it in <pre> tags.
I figured out the problem. I needed to call the method with “../Services.aspx/getServices”. I think my IIS is set up strangely; I’ve had this problem before in different contexts.
Also, I posted all of my snippets in tags, but for some reason, those are getting filtered out. Here’s a test:
var message = “This should be in a *pre* tag with the language specified as javascript.”;
Actually, solving the previous problem with the “../” makes another problem appear. When I try and make a plain vanilla AJAX call with a normal URL (http://www.something.com), .NET or jQuery tries to tack my local URL to the beginning of it. Now I’m really thinking this is a configuration issue with IIS.
I know this may be outside the scope of this blog, but do you have any thoughts?
For those of us not totally in the know on these sorts of things, the ASP.NET AJAX extensions for .NET 2.0 have to be installed (if using .NET 2.0) and the following line has to be added to your web.config under the system.web section:
While much more is needed in web.config or machine.config to fully enable the AJAX framework, the above line appears to be all that’s necessary in order to make page methods functional.
Tony. You really saved my ass here. I’m a complete beginner with ajax and jquery and I just couldn’t work out why nothing worked. I added your line of code and all was good :)
Tony, you are a gem. Thanks thanks a lot – spent hours figuring out why things are not working and just making the change you have said in the web.config, resolved everything!
Dave, I believe you need to make a note of this in the article, as there are lots of web applications which still run on .NET 2.0, as that off mine.
Regards,
Praveen
Hi,
It is really nice article. Thank you very much for you great idea.
“May you all being Happy, Peace and Love”
Thanks, Dave. that saved me hours.
But I got unknown web method error. Still don’t know why.
Thanks Dave for the intro to JQuery, since I am using ASP.Net 2.0 still msg.d threw me off for a second until I read the comments here and realized it should just be msg.
Hey Dave !
Thanks for this post. I came across one, very annoying issue though. Every change made to the static WebMethod code requires the server (either IIS or ASP.WebDevelopment.Server) to be restarted. It seems that the server doees not refresh its sources or even does not recompile them. I’ve been trying to search over the web but to no avail. Are you familiar with such a behaviour ? I use ASP.NET 2.0.
Thanks,
p.s.
Tony – thanks for the httpModules clue ;-)
I haven’t had much trouble with this, but I’ve heard from others who have. One way to deal with it, quick and dirty for development only, is to append a timestamp “cache buster” on the request.
To cure the root problem, you might be able to use this in your web method:
Thanks, but it seems to be not a cache problem. I tried your suggestions before. Looks like the runtime does not reload the assembly. Maybe I omitted sth in configuration.
Does this work in .NET 2.0? It seems to not return anything? I’ve looked at it in firebug to see that the page is returning an Internal server error. Basically the the server response is this:
Here is the jquery call:
Here is my webmethod:
I’m running:
VS 2005
.NET 2.0
IIS 6
With ASP.NET 2.0, you’ll need the ASP.NET AJAX Extensions installed on the server. The site’s web.config will also need to be configured appropriately for ASP.NET AJAX.
You’ll also need to change “msg.d” to just “msg”. The “.d” was added in 3.5, and won’t be present in 2.0.
Thanks Dave,
I’ve got everything installed on the server, but I get the same permissions error. Do you think its an IIS problem? Are any particular users supposed to have execute permissions on the server?
It shouldn’t require any special configuration on the IIS end. Have you modified your web.config for ASP.NET AJAX?
Yes, the web.config has been updated except for the configuration for iis 7.
The Element
I’ll spend some more time searching and let you know what I find out.
Thanks
did you ever resolve this ? I have some code that works perfectly locally but as soon as it is deployed on IIS 6 throws this error..
Excellent article. It’s worth mentioning somewhere in the article that you need to enable AJAX in your web.config for the demo to work. Took me about a half hour to figure that out. Apart from that, superb…!
Hi Dave, good work.
I suppose, jQuery .ajax will always depend on XmlHttpRequest, hence never be able to work crossdomain?
Regards
jQuery supports making JSONP requests, which overcome the cross domain restriction. That’s not bad for read-only usage (e.g. Flickr, Delicious, etc) and trivial write usage where security/reliability isn’t crucial.
Fantastic article.
Is it possible to access a WebMethod on a user control
embedded within the page specified in the URL argument
of the jQuery call?
url: “AjaxGetTime.aspx/GetTime”,
Just curious…
Page methods don’t work in user controls, for whatever reason. You can use an ASMX web service just as easily, if you’re interested in reuse.
Regarding using an ASMX web service with a User Control…
I’ve created a function called ‘Prefs’ in an ASMX web service called ‘calendar_prefs.asmx’.
I have a User Control called ‘calendartoday.ascx’.
The User Control is referenced in an Web Form called ‘Widgets.aspx’.
Within my User Control I’ve set the value of url to the following: url: “calendartoday_prefs.asmx/Prefs”
It fails to execute. Firebug shows the following error: POST http://localhost/MyWidgets/calendar_prefs.asmx/Prefs 500 Internal Sever Error
I’m assuming that my url reference is incorrect, but I’ve tried multiple combinations with no success. Would very much appreciate any assistance.
Since you’re getting a 500 error instead of 404, your path is probably correct. If you can run it with the debugger attached, so you can find out what’s going wrong on the server side.
You were right, Dave. I found an issue with a parameter that I was passing. I should have caught the 500 versus the 404. I’m still learning, thanks for your assistance.
Hey Dave,
Thats a very good post…
I just wanna share my experience here so that if someone come across this difficulty would get rid off…
My function(WebMethod) was not getting called through this, because it was private. So you have to set it as:
public static string YourFunction(string input)
{
// do the cool work here
}
Even just public function doesn’t works…dono why…
That’s correct, Amin. Page methods must be static.
You can read about why here: http://encosia.com/2008/04/16/why-do-aspnet-ajax-page-methods-have-to-be-static/
Dave,
I have been working on a few pages using this jQuery calling PageMethods feature that you demonstrated but now that I have deployed it to a server for testing the calls to the PageMethods always return a 500 error. I have even tried adding a simple Hello World type PageMethod and get the same thing. I have lots of other pages with Ajax and jQuery working fine but have never done this before.
I am stumped. Any help would be appreciated.
The only thing directly related to the jQuery request that would throw a 500 error would be if you were making the call with no data parameter.
Other than that, I’d suggest using Firebug (or something like it) to take a look at the specific exception that’s throwing the 500 error.
The exception is a System.InvalidCastException. The message states that it can not cast a System.String to a System.Web.Services.WebService.
The PageMethod I amcalling is expecting a is filepath in the form of a string.
I do not understand where the Webservice cast is coming from.
I don’t think that’s related to jQuery or the page method. I’d probably using something like elmah or the Application Event Log on the server (if you have access) to get more information about the server side error.
Merry christmas to all.
The returned JSON does always contain an additional element “_type” consisiting of a concatenated string “namespace+class”. Is there a chance to get rid of this?
Regards
The only way I’ve found to avoid that is to return an anonymous type. You can use the return type IEnumerable to return a list of anonymous types.
See this example, for instance: http://encosia.com/2008/02/05/boost-aspnet-performance-with-deferred-content-loading/
Hi Dave,
got your mail. Thanks for the hint. I’ll give it a try. Christmas was phantastic, I hope your’s was great too. Happy New 2009 to you and all readers of this blog.
Strange. For some reasons my latter comments seems to have gone lost.
Never mind. I could manage to get rid of all “_type” decorations using the 3.5 in built JSON serializer. I’m now returning not a typed variable, but a JSON string. This JSON string is decorated with the “d:” thing as usual, but internally much more efficient, than the automatically rendered stuff. Just one or two steps more required, but less traffic and overhead.
Regards
have used jQuery and Ajax for my site and it works
Amazing.
thank u for taking the time to write this article which is very helpful to to me
keep up your good work
I will be a regular reader of ur blog
For some reason the code works fine on my local dev environment but not on the production server. On the prod. server I’m getting “page cannot be found 404″. The status = 404 and statusText = “Not Found”. I’m suspecting AJAX Extension 1.0 is not installed. Is it a requirement? I’ve tried to put dlls in the Bin and still didn’t work.
Is there a way to check whether Ajax Ext. 1.0 is installed or not?
Someone please help?
Thanks!
I think some people have had success deploying DLLs to /bin, but you generally need to run the ASP.NET AJAX Extensions setup on the server and get that installed to the GAC.
Double check your web.config on the server also. Sounds like the HttpHandler or HttpModule section might not be configured properly.
I am having problems accessing the returned value of my web service. if i return just a simple string, no problem. but i need to return an instance of a class, which is just a generic list of another class (which just stores three string values).
Public Class imageInfo
Public address, title, credit As String
Public Sub New()
address = “”
title = “”
credit = “”
End Sub
Public Sub New(ByVal tempImage As imageInfo)
address = tempImage.address
title = tempImage.title
credit = tempImage.credit
End Sub
End Class
Public Class imageGroup
Public Images As New Generic.List(Of imageInfo)
End Class
so for the code listed above i just create an instance of the class imageGroup and then fill it with several instances of the class imageInfo.
example code:
For Each row As DataRow In ds.Tables(“results”).Rows
Dim image As New imageInfo
image.address = row.Item(“address”)
image.title = row.Item(“title”)
image.credit = row.Item(“credit”)
results.Images.Add(New imageInfo(image))
Next
i then return the imageGroup class.
return results
i’m assuming the web service will serialize the return value in a format similar to a multidimensional array, but i can’t figure out the syntax to actually access the information. if i just return an instance of the imageInfo class then I can do something like “msg.address”, which works great. i just don’t know the syntax for returning an instance of imageGroup.
any ideas? make sense?
Never mind. Figured it out.
Glad you got it figured out. If you happen to pass back this way sometime, post what your solution was so that others who find this via a search are able to solve their problem.
I’m assuming it was something like msg[i].address?
Hi Dave, your post was very useful for me!!
Now I have a problem. I need to call a Page Method that interacts with some web controls on the page (literals, buttons, etc…). Both the Page Method and the JavaScript that perform the POST are on the same page.
The problem occur because the Page Method has to be static and then I can’t interact with my objects!!
Is there any solution for this issue?
Thanks in advance (and sorry for the bad english!),
Flea
Unfortunately (in this situation), that’s one of the advantages/limitations of using page methods (or web services). If they had to shuffle around the state of the page and recreate all your controls on the server side, then they would be as bad as an UpdatePanel.
To use the service based approach, you’ll need to re-think it to work without that state information.
Hi Dave,
I saw a problem with this while debugging in Visual Studio. The Page_Load is executing after executing the PageMethod.
I tested with a simple page and put the breakpoints in Page_Load and the static pagemethod.
The pagemethod executed successfully and then the debug control went to Page_Load and executed.
Can you please check?
Best Regards
Anz
It sounds like whatever you’re using to trigger the call to the page method is also raising a form submission (e.g. the enter key in a TextBox, a Button control’s onclick, etc). If unchecked, that will raise a postback on the server side and cause your Page to run through its lifecycle seemingly simultaneously (but actually independent of the page method call).
Hi Dave,,
thank you for your reply.. am sure its not a postback from any controls.. cos the page I have tested does not have anything other than an anchor tag.. am calling the Pagemethod on the click of this anchor.. i don’t know why its happening.. but leave it if its not happening in your end.. may be am doing something wrong..
Best Regards and thanks a lot for your great blog
Anz
Clicking an anchor tag would trigger navigation in the browser. Same result.
If you’re using jQuery to handle the click event, add preventDefault, like this:
Can you give me a sample with passing parameters?
This later example passes parameters (the syntax is identical between page methods and web services): http://encosia.com/2008/08/20/easily-build-powerful-client-side-ajax-paging-using-jquery/
I tried this code, its working absolutely fine. I made a slight change in this i used an ASP:Button control instead of DIV. The click event of this button fetches the date time into a ASP:Label control, but the problem is that due to page postback after the JQUERY call the label does not show the time. Then I used control the code is working fine.
How to stop the asp:button from causing postback
Assuming you’re wiring up the Button’s click event through jQuery, you need to use preventDefault() to prevent the Button from triggering a POST. Something like this:
Hi.
Thanks for posting this script..
I am in between such a requirement where i need to make a call to a php page(form) from a jsp page. I have applied this script and it is working for IE only. Firefox shows me a an error(in firebug) as
[Exception... "'call method XMLHttpRequest.open *M0>*$ 0( $G *>,p&@ 9H' when calling method: [nsIDOMEventListener::handleEvent]” nsresult: “0x8057001e (NS_ERROR_XPC_JS_THREW_STRING)” location: “” data: no]
I studied a few blogs and its suggested to set AutoComplete=Off for the textboxs under such error. But here we dont have any input controls. How can i solve this error.
Munish.
I see this being used for strings a lot, but what if I want to set values to a existing control, like a radio button list? I know I could put the HTML for all the inputs together in the page method, but how would I access them from codebehind on a form submit? Anyone try this?
I’d suggest sending back the index of the radio button (and its ID if necessary) to select, and then act on that after the request completes.
The web method without parameters works fine, while with parameters does not.
Is there anyway we can do this without ASP.NET Ajax?
That depends on what you mean by ASP.NET AJAX. This does not require that you use a ScriptManager or UpdatePanel on the page, nor any of MicrosoftAjax.js on the client-side.
As long as you have the AJAX extensions installed on ASP.NET 2.0 or have ASP.NET 3.5, this will work.
Hi there,
I found great ideas and discussing on your Web site.
Well done ! Thanks for that and keep on doing
Greetings from germany , Thomas
Hi Great article.
I have one question. Everything works great unless the string being returnd from the web service is relatively small; otherwise ‘Undefined’ is returned. Is there a max length?
error: function(XMLHttpRequest, textStatus, errorThrown){ alert( errorThrown )
Thanks!
If your responses are very large (larger than 102,400 characters), you may need to adjust the maxJsonLength setting on the serializer: http://msdn.microsoft.com/en-us/library/bb763183.aspx (see the second section)
Can I make webmethod call from html page using jquery?
I tried to call a web method from .aspx page and flushing whole result to div tag.
It didn’t work.
Is this only work .aspx page?
Thanks,
Raj
The jQuery code above does work from plain HTML pages, calling a page method defined on an ASPX page. You can call an ASPX page’s page methods from anywhere, as long as its not cross-domain.
I’m trying this technique using JQuery 1.3.2, Visual Studio 2005, ASP.NET 2.0 with ASp.NET 2.0 AJAX Extensions 1.0. When I debug the $.ajax() call in the page I find that it appears not to be calling my page method but bombs out straight to the error function. Here’s what I’m doing:
$(function() {
$.ajax({
type: “POST”,
url: “JSONAJAXDemo2.aspx/GetDiagnostic”,
data: “{}”,
contentType: “application/json; charset=utf-8″,
dataType: “text”,
success: function(callResult) {
$.log(“Success”);
},
error: function (XMLHttpRequest, textStatus, errorThrown) {
$.log(“Error: ” + textStatus);
}
});
});
});
I’ve also got a page method called GetDiagnostic -
[WebMethod]
public static string GetDiagnostic()
{
return “Hello this is the GetDiagnostic method”;
}
When the code drops into the error method the textStatus is “parsererror” and the XMLHttpRequest contains the whole HTML source code of the whole rendered page. As far as I can see the page method id never called at all. Any ideas on what this could be?
I wouldn’t think it would cause that particular error, but your JavaScript has one }); too many at the end.
Hi,
I have been trying for hours to get this example to work with no luck. I am using VS2008, .net 3.5.
my code below:
code behind:
I would love to see this working.Please help!
That all looks correct. How is it failing?
It just doesn’t do anything, i click and nothing happens. I added an alert(‘hi’); and this pop’s up when the div is clicked. Looks like nothing is returned by the GetDate(); method?
So far, this is working great for me. The only one thing that I can’t figure out, is how to I pass parameters to my page method?
What’s the correct syntax for the data parameter, if my method expects two integers?
Nevermind, I found it in the thread about five miles further up. Sorry for being stupid! :-)
http://encosia.com/2008/08/20/easily-build-powerful-client-side-ajax-paging-using-jquery/
Hi Dave,
How about passing a querystring on the data options? Below is not working. :(
javascriptFile.js
You’d need to change your data parameter to:
You can also use JSON.stringify to avoid the string concatenation and keep things cleaner: http://encosia.com/2009/04/07/using-complex-types-to-make-calling-services-less-complex/
Thanks a lot!
Hi there, I found great ideas on your Web site. Well done ! Thanks for that and keep on doing Greetings from germany
Great post, really helpful. In the past I’ve not used page methods much because you can’t define them in a control, a master page or a base page. Does this restriction still apply when calling using jQuery?
Yes, the same restrictions apply.
In all of those situations, you can use an ASMX “ScriptService” to provide the same functionality in the implied, more centralized fashion.
Hi Everyone
This works if I return a “string” from the method but when I am trying to return a object of Custom type say “Person”, I get an error in Visual Studio while debugging. The error says “Microsoft JScript runtime error: ‘length’ is null or not an object”.
Any Ideas??
Its resolved. It was a problem with jQuery syntax. I was displaying a JS object with $(“#Result”).text(msg.d)
This example works fine with VS 3.5 studio, .net 3.5 but the same code does not call CS page method when I tried with asp.net 2.0.
Why ? Do I need previous version JQuery Library
Make sure the ASP.NET AJAX Extensions are installed. Also, in 2.0, you won’t need to use the the .d. msg.d in the example above would be just msg in 2.0.
I have everything working fine but when I attempt to call data that is over 60kb it fails. Is there some kind of limit on a amount of data you can call???
Any help would be great!
Hi Paul,
Put this in your web.config
Thanks everyone, the call is now working!
Hello … I am using ASP.NET 2.0 in my website and I wasn’t happy with the idea of installing AJAX libraries and framework in order to get this example working with my project. So after some hours of research I did this and works for me. Look!
1st step…
This is the javascript code as I am finally using it…
What doeas it mean?
1. Please note how I am managing the parameters sent to my url: {‘s’ : postId }.
2. Then I am commenting contentType parameter. I SPENT A LOT OF TIME TO FIGURE OUT THAT THIS WAS ONE OF MY BIGGEST PROBLEMS…
3. Now look please to what I do when on success
3.1. ASP.NET 2.0 .asmx services will return XML (I know that ASP.NET 3.5 and AJAX extensions will JSON instead, but we are talking about keeping everything 2.0 without extensions so manipulating XML will be part of the job.
3.2 My GetPostByID method returns HTML inside a String so I have to get it by using
If you’re retrieving HTML and don’t want to include some sort of JSON serializer on the server-side, it probably makes more sense to make calls to a HttpHandler that does nothing but return that HTML. There’s no need to add the overhead of XML, XML serialization on the server, and XML deserializaton on the client.
keep up your good work. thank you.
Hello!
There is something strange with this GetDate() function: if I change it to return “Hello world is not working”, if I change it from DateTime.Now.ToString(); to DateTime.Today.ToShortDateString(); it still returns the date in the first format even (!) if I refresh the page or close the browser (!!).
Thanks!
Make sure you’ve recompiled the code. Beyond that, your browser’s caching settings may be getting in your way. $.ajax accepts an optional parameter to adjust that, called “cache”. Try the call like this:
Hello!
Thank you for your fast and kind response. Will try this. I’m very fresh to jQuery and don’t have so much experience in programming if I’m honest.
It’s a quite long read but do you have any idea how can I accomplish this:
http://forums.asp.net/t/1498568.aspx
I’m having troubles with this problem for very looong time. I would very appreciate your time and support.
Thanks for posting this. It works fine but it took me a little while to realise I had to add ‘using System.Web.Services;’ at the top of the webpage. Without it, the compiler didn’t recognise the WebMethod attribute.
Yes, I put it in my code-behind file as part of a using statement:
using System.Web.Services;
Didn’t work for me.
Sorry you’re having trouble, Tom. Without knowing more detail about what you were trying that didn’t work, I’m not sure what the problem was.
You might find this example useful: http://encosia.com/2008/08/20/easily-build-powerful-client-side-ajax-paging-using-jquery/
It uses this same technique, but also includes source code.
Was finally able to get it working to retrieve my value from the server-side. Was using the wrong version of jQuery before and forgot to update the webmethod name in the Default.js.
Is there a way to query the same webmethod over and over again until it reaches a certain value (i.e. 100), but report that value in the form of a table cell width, instead of as Div text? Basically trying to create a progress bar… table has 2 cells – first would grow as the other shrinks.
You could use the jQuery UI Progressbar widget to handle that more cleanly than with a table. Assuming the service always returns an integer, something like:
The only problem with the jQuery issue, at least in my case, it was that the server-side code with all finish before the jQuery (client-side) code with go through and build a bar. This had to happen while a server-side event was going on, not after it was already done.
The idea is that you’d poll your server-side process for its progress and adjust the jQuery progress bar after each callback. That’s what you described in your previous comment, isn’t it?
And that is what I was doing – I would use a webmethod call to a function that would return to me the value of a global variable in the code-behind. I did this for 2 variables, one function each. That global variable would get updated as the server code ran – as it was polling records in a database in a “foreach” loop and updating this global counter variable as it went. Another global variable was assigned dt.Rows.Count – the total rows in the DataTable, and had a webmethod function call for it. Problem was, even though I had a JavaScript function to ask for the value in a loop until it equaled the total rows, it never showed progress, it was just instantaneous – the postback didn’t happen until the database loop had run. By then, you get a bar that is all the way done, instead of one that got generated on the fly as the database was being looped. If you have a way to do this with jQuery, please share, but I couldn’t get it to run until the server-side code completed, by which time it was too late to show its progress in a progress bar. Appreciate the help.
Thanks, Tom
If I understand, what’s getting you is that changes to a “global” variable in that Page instance isn’t necessarily visible to the webmethod call in a separate HttpContext. Consider using a Session variable instead, which is shared as you would expect.
Hello,
Can this be done in .net 2.0 Framework?
thank you,
Yes. You need the ASP.NET AJAX Extensions v1.0 installed and your project’s web.config updated accordingly to expose the “page method” functionality.
You’ll also need to be aware that the “.d” isn’t present in the response from 2.0 JSON services.
Thanks for the reply; i only asked because i currently am searching for ways to get rid of ScriptManager and all the axd files it produces(i had a update panel implementation). It’s just to much and i find it to be quite a waist of resources.
So, my priority is to have ajax without all those files.
We tried to find a way to keep PageMethods without ScriptManager, or somehow to call a server side function from Javascript in front end, but that did not work till now.
What we could do, is to use a aspx file as a source for XmlHTTPRequest. It is ok, meaning that it does the job. However, i would like to implement your idea, so i will try it as you suggested.
Thank you,
Hello, Very good article. I will continue to pursue this article, as it is written is very interesting. Since we are interpreted very much on good information. Best regards :-)
Thanks, it was pretty easy to get /GetDate working by following your example.
The next thing I did was to add /HelloWorld to the same .aspx page. The result: “Unknown web method” Say what?
I’ve googled this high and low and found some stuff about VS caching the autogenerated code. But I cleared everything I can find and still had this error.
Then I found the reason – I forgot to make it static.
I just want to say thanks a lot .NET for allowing a webmethod to compile when it wasnt static. Thanks a lot .NET for the *really* helpful error message that I spent hours trying to resolve.
This blog is my favorite, congratulates.
First of all, many thanks to Dave Ward. It’s just fantastic work.
However, Dave, I have one question. Is it neccessary to include contentType: “application/json; charset=utf-8″ in our ajax call ? My call was returning error without this, if I enter any other dataType option like html,text,xml etc. Also, if I don’t write anything at all, it returns the entire page html, though I’m calling a page method.
Yes, the content-type is necessary. If you call a page method without the correct content-type (or with a method other than POST), ASP.NET will treat the request as a normal GET request to the ASPX page itself.
This is really a cool article to read. I shall be working with it for my website.
Thanks.
I’m having quite the struggle to make it work.
I’m using VS2008 (ASP.NET 3.5) with jQuery 1.4.2
It all seems to work (on firebug I see that the POST gets done, and I get the correct reply [the date]), but the DIV does not update.
I’m using IIS 7.5 on a Windows 7 64 box. I’ve been headbanging with this for two days… but don’t seem to get it to update de DIV.
Take a look this more complete example of using jQuery with page methods. That one has a source download at the end, which might help.
Got the problem solved. Usually the bug is between the PC and the screen, and this was no exception:
‘Success’ works…while obviously ‘Sucess’ does not…
Thx anyway and congrats for some good posting =)
hi as asked v first i want to know ho pass value to the web method using the ajax.??
This works fine as posted, but when I tried to adapt it to post some xml, it didn’t work. I can’t seem to get it working with xml at all – is there a particular reason? or just an error in my code somewhere?
This isn’t intended to work with XML. By setting a content-type of application/json, you’re telling the server to expect JSON. The idea here is specifically to avoid the bloat of XML for client-side callbacks.
I have developed a plugin for jQuery which allows you to easily pass parameters in pagemethod.
You can find an example in readme.txt
Download it from: here
Thank you for your great post.
I want to enable short-cut for my application. Application is completed and I just want to add some functionality to it.
I’d find 2 Jquery Library which can help me to enable short-cut for my application.
But as a short-cut is just catching a key combination, I’m wonder how can I call the server methods which a short-cut key should fire?
Can you help me please?
I also ask this question in http://stackoverflow.com/questions/2996293/how-to-fire-server-methods-with-jquery
Thank you In Advance
When an exception occurs within a PageMethod, the Application_Error method (defined in the global.asax) is not being called.
I want to log every error that gets thrown within a PageMethod, but cannot find a way to have a central event to hook into to accomplish this.
One solution to that is to wrap the contents of every PageMethod in try/catch block, but I want to avoid this for obvious reasons.
here is my class containing webmethod sayHello() . But i’m getting build error as follows
The type or namespace name ‘WebMethod’ could not be found (are you missing a using directive or an assembly reference?) C:\Documents and Settings\sanker.r\My Documents\Visual Studio 2008\Projects\sanyo\sanyo\page3.aspx.cs 16 10 sanyo
Code
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace sanyo
{
public partial class page3 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
[WebMethod]
public static string sayHello()
{
return “hello every one”;
}
}
}
You need to add System.Web.Services to your “usings”.
Firebug says it is missing a parenthesis after the argument list but i ain’t missing.
Could someone post the working code
As one of the person by name Ross asked, is there a solution yet as to directly call a method on a DLL (not via a page). for example can we have the url as url:test.vb/GetStatus ? The only way i think is of creating an httphandler / module and registering the .vb filetype in IIS and handle it that way.
A web service is my preferred method for wrapping a business logic assembly with an external API. An HttpHandler would be very similar, but something like a ScriptService has the advantage of automatically handling JSON serialization and deserialization.
Actually this is Possible by using the first Ajax framework written for ASP.NET.
I have used it in YetAnotherForum and some new features in YAF (Thank Mod, Favorite Topics, Albums…) are implemented using AJAXPRO (A.K.A Ajax.Net Professional).
You can call literally ANY method even if it’s defined in a dll.
Hi ,
I am using web method static type and call by same jquery . its working fine on local system but when i put on server then not working . Jquery not call that web static type methods its return 12152 unknown error . please anyone give me solution , thanks….i hope anyone help me
Hi
What about security page method vis a vis asmx service.
Is page method more secure and will it work with windows integrated authentication on IIS.
Please advise.
Thanks
San
Both work the same way, in terms of security. The page methods are basically just shorthand for ASMX’s ScriptMethod. Both approaches run through the HttpHandler that handles security, so you can use integrated or forms authentication just like you would with an ASPX page.
So I have everything working great, at least when I run in debug in VS 2008. As soon as I publish it out to our dev server, I get 500 Internal Errors when it’s trying to access the page methods that work locally.
I tried publishing to my local IIS server, but apparently our IS&T department has put some weird policy rules in place (none of my dev sites on my system work anymore).
I’ve dug through Firebug to see what’s going on, but all that ever gets returned is {“Message”:”There was an error processing the request.”,”StackTrace”:”",”ExceptionType”:”"}.
It seems like maybe there’s something not right with the IIS configuration perhaps?
If you have access to the dev server, take a look at the event log to find more detail on the errors. You could also temporarily turn custom errors off in the web.config, so that more error detail will be present in the response.
I’m unfortunately not seeing anything out of the blue. I’ll try modifying the web.config and see what happens.
what verison of jquery neeaded for jQuery.Ajax?
Any version should work. I can personally confirm $.ajax() works against .NET services in jQuery 1.2.x, 1.3.x, and 1.4.x.
I’ve really enjoyed this posting and the replies so far. However, I haven’t found a solution to my problem. Followed the code earlier to call a page method but unable to get the ajax call to work. The difficul;ty with mine is the page method is in the code behine, in the c# code. Here’s the javascript code I’m trying to get working.
Sorry, omitted details of the result. These are the same whether I target the .aspx or the aspx.cs files in the url.
The messages produced by the error section are “error”, “500″, “Internal Server Error”.
Thanks
goof piece of work ..excellent..I’ve trying to do this long time a go..but no sucess until now..thnx!
This post is still relevant and excellent. Great job – and Thanks!
Is there any way to implement page method with custom route handling?
In particular the problem I’m facing is content on a given Default.aspx is dynamic, so it depends on an ID supplied in URL, e.g. /customer/3 then retrieves customer with ID 3 on Default.aspx. Page methods would then depend on this ID to carry out a specific task.
I am currently using asmx web service as a work around, but it seems to me page methods would encapsulate the functionality much better.
I think that’s probably not possible with page methods. You could use URL rewriting to map the
/customer/3toDefault.aspx/CustomerMethod?customer=3pretty easily, but page methods won’t accept their parameters that way.The new “Web Api” version of WCF would be a good choice for this. It accepts parameters via querystring and returns JSON by default if the request is coming from jQuery, which is nice.
I suspected as much, which is a shame. I don’t really see any advantage of using WCF over my current asmx implementation – in practise it’s only really used to return friendly errors.
The actual functionality is concerned with changing customer details, so strict authentication/validation is taking place, which can only really occur during the whole page life cycle (I’m doing it through base pages and session objects). Come to think of it, there was no way that I could have used page methods and skip the page onInit checking.
How about exception handling in the Static PageMethod functions?
I mean currently , in code behind , I put the complete logic , residing inside the Static method inside try-catch block?
Is there any easy way to catch exception & redirect to error page without sending any raw exception to client side at all?
Also how about validations to all the parameter?
Currently I manually validate for type, length, regular expressions, htmlEncode,
Is there any better approach?
Exceptions, especially parameter parsing exceptions, are definitely a weak spot in PageMethods (and ASMX). I’ve heard of people using the global.asax events to register global error handlers that do apply to these service endpoints, but I haven’t experimented with that much myself.
You can however handle exceptions gracefully on the client-side, and even bounce those exceptions back to a logging service. I’ve done that in the past to get purely client-side errors logged in Elmah and then expanded that approach to also bounce 500 responses to $.ajax() requests up to that logging service.
For validating parameters, I’ve had decent success using DTOs as input parameters and then adding an IsValid() method to them so that I can sanity check them easily in the service method and react accordingly.
Thanks Dave. My earlier question on exception & Validation totally pertains to server side . I am very happy with DTO & whatever client side way of posting the form values. Client is fine — but what I worry is — using tools like fiddler, we can alter the request, bypass any client Validation , read any exception thrown to client —– so now I want answers, — for server side part of it.
Firstly the exception –
I have put all the code for any Static WebMethod in try-catch , but could never get global.asax’s Application_error to fire. It just ignores that event handler. So what I did was — I have my own static error function in a class file where I do the same thing as Application error & then throw some generic fancy error to client.
But then I have to repeat this code (calling that function) for every pageMethod. I don’t like that. Can you give me any pointer how to hook Global.asax OR httpModule to capture exception from Static Page Methods?
Secondly the Validation –
I didn’t get what you mean by IsValid function in the Static Method? I am assuming it’s your own static IsValid function. Because the framework’s validation Or any validator’s validate function gets invoked only on PageSubmit. Not on this kind of AJAX calls. So those validators don’t add any value on server end, although they are usefull on client end.
Currently I have developed all kind of custom functions similar to the standard validators to sanitize the input — on server end. I have the DTO approach just like you had given in this example on the client end– but my main concern is what happens inside the Static Methods.
So was just curious if there is any better way to validate other than manually checking each input for type,length,htmlEncode any plain text, regex to get rid of injection in the Static WebMethods.
How to call the web method through Custom HTTP Handler? Below is the scenario,
1. I have a web method called HelloWorld in .aspx page
2. I have a custom Http Handler for .aspx page. Something called ASPXHandler.
3. i’m trying to call HelloWorld web method from JQuery. Following error is throw in ProcessRequest method of ASPXHandler,
There is no build provider registered for the extension ”. You can register one in the section in machine.config or web.config. Make sure is has a BuildProviderAppliesToAttribute attribute which includes the value ‘Web’ or ‘All’.
If you’ve got a custom HTTP Handler that’s causing trouble, I’d probably suggest using an ASMX service instead. They work with jQuery exactly the same way.
i have implemented using ASMX for now, but curious about why not page web method
Web.config lines for your handler could help to comments accuracy …
I say great article as well. I’ve been playing with this and here’s what I discovered:
1. If I use page methods and return an IEnumerable with creating dynamic types from my Entity Framework entities, things work fine:
2. If I try the exact same code from an “Ajax-enabled” WCF service in the project, I get at 12152 error back in javascript. For some reason, it can’t handle the anonymous type conversion then.
I tried making it List<object> as the return type from WCF and add the anonymous types to a List and return that from WCF. Still 12152 message in my jQuery error handler.
What finally did work is creating an actual class: PracticeDTO with the properties I used above in the anonymous type. Then things worked great. IEnumerable or List<object> as return type work.
So, if you see the 12152, look into what type you’re returning.
When I implemented this in my ASP.Net 4.0 project, I couldn’t get it to work… It wouldn’t show anything or show any errors… I spent 5 hours wasting time thinking I needed to install the Ajax Library, or modify my Web.Config file… Turns out I was doing this in my script…
when I should have been doing this:
notice the “.d”
BTW… I would really like to thank you… This is making my project so much smoother!
Also, wanted to share this…
This way, if the end user tries to call your web-browser by modifying your client code, instead of serving up the data, it will show an error…
It’s nice to see that you’ve got a good approach to security. A lot of people struggle with the security aspect when moving more logic to the client-side (which implies that they weren’t really giving it enough attention before).
Glad to hear that this approach is working well for you. It really changed how I approached working with WebForms.
Very helpful Dave.
Thanks.
John.
In development environment this worked great for me. I have some controls in a subfolder of my site that are rendered on a page in the root of my site using the LoadControl method (C#). The codebehind files for these controls have webmethods that I call with jQuery AJAX. Like I said, it all worked fine in development (IIS 6) but now on the production server (IIS7.5) I am getting 404 error when the WebMethods are called. The controls load on the page just fine so the files are definitely there, but the ajax call results in a 404. I’ve checked the address of the request and it is correct. Have any ideas as to what could cause this?
Interestingly, asmx files with WebMethods work just fine. I really need to be able to keep these webmethods in the codebehind of the controls though.
To my knowledge, page methods can only be be defined in ASPX code-behind, not in ASCX user controls. You’re seeing a 404 on those because IIS/ASP.NET doesn’t allow direct requests for ASCX files.
Does your development environment have serving ASCX controls enabled in IIS? I’ve never tried it, but I suppose that could have a side effect of making page methods work in their code-behind.
Yes, it worked in the development environment IIS 6.
To serve the ascx files I added this in the web.config:
Would I need to do something else in IIS7.5 to serve ascx files? Also, curious, is it a bad idea to serve .ascx files?
Thanks for your great blog. It has helped me multiple times over the past few years!
That’s interesting. I didn’t know that would work, but I guess it makes sense that it could.
In IIS7+, you’ll need to add that handler configuration in the <system.webServer>’s < section instead. You can also configure it through the IIS Manager if you have access to that on the server (or remote access rights to the management interface).
It still had problems there. After some research, it turns out that the ability to do this in IIS 6 wasn’t really meant to be there. So I guess that got nixed in IIS 7+.
You can relax IIS7′s default request filtering on *.ascx by also adding this in the web.config:
That doesn’t quite get it working right, but it might be a step in the right direction.