jQuery AJAX calls to a WCF REST Service
Since I've posted a few jQuery posts recently I've gotten a bunch of feedback to have more content on using jQuery in Ajax scenarios and showing some examples on how to use jQuery to cut out ASP.NET Ajax. In this post I'll show how you can use jQuery to call a WCF REST service without requiring the ASP.NET AJAX ScriptManager and the client scripts that it loads by default. Note although I haven't tried it recently the same approach should also work with ASMX style services.
WCF 3.5 includes REST functionality and one of the features of the new WCF webHttp binding is to return results in a variety of ways that are URL accessible. WCF has always supported plain URL HTTP access, but it's not been real formal and had somewhat limited functionality as parameters had to be encodable as query string parameters. With the webHttp binding there's now an official WCF protocol geared towards providing ASP.NET AJAX JSON compatibility (using WebScript behavior) as well of a slightly cleaner raw JSON implementation (basic webHttp binding).
You can return XML (default), JSON or raw data from WCF REST services. Regardless of content type, natively WCF always wants to return content in a 'wrapped' format which means that both inbound parameters and outbound results are wrapped into an object.
Let's take a look at the message format for a REST JSON service method.
[ServiceContract(Name="StockService",Namespace="JsonStockService")]
public interface IJsonStockService
{[OperationContract]
[WebInvoke(Method="POST",
BodyStyle=WebMessageBodyStyle.Wrapped,
ResponseFormat=WebMessageFormat.Json
)]StockQuote GetStockQuote(string symbol);
..
The input message on the wire looks like this:
{"symbol":"MSFT"}
The response looks like this:
{"GetStockQuoteResult":
{"Company":"MICROSOFT CP",
"LastPrice":30.00,
"LastQuoteTime":
"\/Date(1208559600000-0700)\/",
"LastQuoteTimeString":"Apr 18, 4:00PM",
"NetChange":0.78,
"OpenPrice":29.99,
"Symbol":"MSFT"}
}Notice that in both cases an object is used. For the inbound data all parameters are wrapped into an object and rather than just passing the value, the name of the parameter becomes a property in the JSON object map that gets sent to the server. This is actually quite useful - if you're just sending a raw JSON structure you could only pass a single parameter to the server - and that option is also available via the Web BodyStyle=WebMessageBodyStyle.Bare option on the service method.
The outbound result set is also wrapped into an object which is a lot less useful. This is a hold over from WCF which wraps all responses into a message result object, which usually makes sense in order to support multiple result values (ie. out parameters etc.). In a Web scenario however this doesn't really buy you much. Nevertheless if you want to pass multiple parameters to the server you have to use this wrapped format along with the result value.
Calling with jQuery
If you're using jQuery and you'd like to call a WCF REST service it's actually quite easy either with bare or wrapped messages. Bare messages are easier to work with since they skip the wrapping shown above, but as I mentioned you're limited to a single input parameter. So if your service has any complexity you'll likely want to use wrapped messages.
You can opt to either call services using the ASP.NET Ajax logic (WebScriptService behavior) or using the raw service functionality which is shown above.
To call these methods with jQuery is fairly straight forward in concept - jQuery includes both low level and highlevel methods that can call a URL and return JSON data. The two methods available are $.getJSON() which automatically parses result JSON data and $.ajax(), which is a lower level function that has many options for making remote calls and returning data.
getJSON() is useful for simple scenarios where the server returns JSON, but it doesn't allow you to pass JSON data TO the server. The only way to send data to the server with getJSON is via query string or POST data that is sent as standard POST key/value pairs. In all but the simplest scenarios getJSON() is not all that useful.
The lower level $.ajax method is more flexible, but even so it still lacks the capability to pass JSON data TO the server. So little extra work and some external JSON support is required to create JSON output on the client as well as dealing with Microsoft Ajax's date formatting.
Personally I prefer to use a wrapper method for making JSON calls to the server to encapsulate this functionality. Note although this method seems somewhat lengthy it deals with a few important issues that you need to take care of when calling WCF REST Services:
// *** Service Calling Proxy Classfunction serviceProxy(serviceUrl)
{var _I = this;
this.serviceUrl = serviceUrl;
// *** Call a wrapped object
this.invoke = function(method,data,callback,error,bare)
{// *** Convert input data into JSON - REQUIRES Json2.js
var json = JSON2.stringify(data);
// *** The service endpoint URL
var url = _I.serviceUrl + method;
$.ajax( { url: url, data: json,type: "POST",
processData: false,
contentType: "application/json",
timeout: 10000,dataType: "text", // not "json" we'll parse
success: function(res)
{ if (!callback) return;
// *** Use json library so we can fix up MS AJAX dates
var result = JSON2.parse(res);
// *** Bare message IS result
if (bare)
{ callback(result); return; }
// *** Wrapped message contains top level object node
// *** strip it off
for(var property in result)
{ callback( result[property] );break;
} },error: function(xhr) {
if (!error) return;
if (xhr.responseText)
{var err = JSON2.parse(xhr.responseText);
if (err)
error(err); else
error( { Message: "Unknown server error." })
}return;
} }); }}
// *** Create a static instancevar Proxy = new serviceProxy("JsonStockService.svc/");
WCF services are called by their URL plus the methodname appended in the URL's extra path, so here:
JsonStockService.svc/GetStockQuote
is the URI that determines the service and method that is to be called on it.
The code above uses the core jQuery $.ajax() function which is the 'low level' mechanism for specifying various options. Above I'm telling it to accept raw string input (in JSON format), convert the response from JSON into an object by evaling the result, as well as specifying the content type and timeout. Finally a callback handler and error callback are specified.
Note that I override the success handler here to factor out the wrapped response object so that the value received in the callback handler is really only the result and not the wrapped result object. More on this in a second.
The call for the above StockQuote(symbol) call looks like this (including some app specific code that uses the result data):
var symbol = $("#txtSymbol").val();
Proxy.invoke("GetStockQuote",{ symbol: symbol },
function (result)
{ //var result = serviceResponse.GetStockQuoteResult;
$("#StockName").text( result.Company + " (" + result.Symbol + ")" ) ;
$("#LastPrice").text(result.LastPrice.toFixed(2));
$("#OpenPrice").text(result.OpenPrice.toFixed(2));
$("#QuoteTime").text(result.LastQuoteTimeString);
$("#NetChange").text(result.NetChange.toFixed(2));
// *** if hidden make visible
var sr = $("#divStockQuoteResult:hidden").slideDown("slow");
// *** Also graph it
var stocks = [];
stocks.push(result.Symbol);var url = GetStockGraphUrl(stocks,result.Company,350,150,2);
$("#imgStockQuoteGraph").attr("src",url);
}, onPageError);Parameters are passed in as { parm1: "value1", parm2: 120.00 } etc. - you do have to know the parameter names as parameters are matched by name not position.
The result is returned to the inline callback function in the code above and that code assigns the StockQuote data into the document. Notice that the result returned to the callback function is actually NOT a wrapped object. The top level object has been stripped off so the wrapper is not there anymore.
If you look at the the ajaxJSON function, you can see that it looks for the first result property in the actual object that WCF returns and uses IT to call the callback function instead - so it's indirect routing. This saves you from the one line of code commented out above and having to know exactly what that Result message name is ( WCF uses <methodName>Result). Not that one line of code would kill you, but it's definitely cleaner and more portable.
The same approach should also work with ASMX style services BTW which uses the same messaging format.
JSON encoding
Note that the ajaxJSON function requires JSON encoding. jQuery doesn't have any native JSON encoding functionality (which seems a big omission, but was probably done to preserve the small footprint). However there are a number of JSON implementations available. Above I'm using the JSON2.js file from Douglas Crockford to serialize the parameter object map into JSON.
There's another wrinkle though: Date formatting. Take another look at the stock quote returned from WCF:
{"GetStockQuoteResult":
{"Company":"MICROSOFT CP",
"LastPrice":30.00,
"LastQuoteTime":
"\/Date(1208559600000-0700)\/",
"LastQuoteTimeString":"Apr 18, 4:00PM",
"NetChange":0.78,
"OpenPrice":29.99,
"Symbol":"MSFT"}
}
There's no JavaScript date literal and Microsoft engineered a custom date format that is essentially a marked up string. The format is a string that's encoded and contains the standard new Date(milliseconds since 1970) value. But the actual type of the date value in JSON is a string. If you use standard JSON converters the value will be returned as a string exactly as you see it above. I've talked about the date issues, and hacking existing JSON implementations before. I've modified Crockford's JSON2.JS to support the Microsoft date format so it properly encodes in and outbound data. You can download the hacked JSON2_MsDates.zip if you're interested. You can look at the code to see the modifications that were required, which essentially amounts to pre filtering parsed data before evaling on the .toJSON end and dropping the Data format that Date.prototype.toJSON() produces and instead creating a string in the required format above when doing object encoding.
Bare Messages
If you want a cleaner message format and you're content with single parameter inputs to functions then the WebMessageBodyStyle.Bare can work for you. Bare gives you a single JSON parameter you can pass that is automatically mapped to the first and only parameter of a method. You can't use Bare with any service methods (other than GET input) that include more than one parameter - the service will throw an exception when you access any method (beware: it's a RUNTIME error!).
Bare messages are easier to work with but they are limited because of the single parameter. You can use a single parameter on the server and make that input a complex type like an array to simulate multiple parameters. Using input objects or arrays can work for this. While this works realize that WCF requires an exact type match so any input 'wrapper' types you create yourself have to be mappable to a .NET type.
My first instinct with WCF's web bindings was always to use Bare, but ultimately the wrapped format provides more flexibility even if it is a little uglier on the wire. For AJAX services wrapped seems to make more sense.
Ideally, I would have preferred even more control - wrapped input messages and bare output messages, but I guess you can't have everything <g>...
Other Input Alternatives
Passing JSON messages is one thing you can do - the other option is to pass raw POST variables, which is something that can be done natively with jQuery without requiring a JSON encoder. Basically jQuery allows you to specify data as an object map, and it can turn the object into regular encoded POST parameters.
[OperationContract]
[WebInvoke(Method="POST",
BodyStyle=WebMessageBodyStyle.Bare,
ResponseFormat=WebMessageFormat.Json
)]StockQuote GetStockQuote(string symbol);
You'd also need to mark your class:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class JsonStockService : StockServiceBase
and enable ASP.NET compatibility in web.config (see my WCF REST Configuration Post for details)
If you prefer the simplified logic and you can use POST input data (which works well if you rather post back to a handler or the same ASPX page) you can get away with the following:
function ajaxJsonPost(method,data,callback,error)
{var url = "JsonStockService.svc/" + method;
$.ajax( { url: url, data: data,type: "POST",
processData: true,
contentType: "application/json",
timeout: 10000,dataType: "json",
success: callback, error: error }); }When you send data like this you can actually change the message format to Bare and get just a raw object response. jQuery can either except a raw POST string for the data parameter or an object whose properties and values are turned into POST key value pairs.
If you want to use POST behavior with WCF though, you need to enable ASPNET Compatibility on the REST service - otherwise the HttpContext.Current.Request is not available since WCF REST by default is trying to be host agnostic. For more information on how to configure WCF REST services check my previous post on WCF REST configuration last week.
This format might be preferrable if you are indeed building a public API that will be externally accessed. Raw POST data interchange is more common for many Ajax libraries, and also lends it self to straight HTTP clients that don't have JSON encoding features built in. For public APIs this makes plenty of sense. Remember that if you care about date formatting you may want to add the explicit JSON2 parsing code into the success callback (I left this out here for simplicities sake).
Error Handling
One more issue you'll want to be very careful of with WCF REST Services when you're using non-WebScriptService (ASP.NET AJAX style) behavior: When an error occurs WCF unfortunately throws an HTML error page rather than a JSON or XML fault message. That's a big problem if you want to return meaningful error messages to your client application - the only way to retrieve the error is by parsing the messy and very bulky HTML document returned.I've tried finding some way to get the REST services to throw a full JSON based error message and I haven't found a way to do this. JSON error messages seem to only work when you're using WebScriptService which is the full ASP.NET AJAX emulation. Under WebScriptService behavior the message returns the standard Exception like structure that includes a .Message and .StackTrace property that lets you echo back errors more easily.
In the end this means that even if you are using a non-MS Ajax client it might be the best solution to use the ASP.NET AJAX style WebHttp binding, simply because it provides the behavior that you most commonly require. There's nothing lost by doing so. You don't incur any client ASP.NET AJAX client requirements, but you do get the wrapped format input and exceptions properly wrapped on errors, plus this format is easier to implement because it doesn't require any special attributes on each individual operation/method as it's a fixed format. On the downside you do lose the ability to use UrlTemplates which might be useful in some situations, but it's probably not a common scenario that you need this for pure AJAX services.
Code Samples and libraries are posted from my ASP.NET Connections Sessions here.
Other Posts you might also like
The Voices of Reason
# re: jQuery AJAX calls to a WCF REST Service
You can also find a recorded video of their MIX08 presentation and some more details in this blog post: http://blogs.msdn.com/vbertocci/archive/2008/03/06/wcf-rest-at-mix08-the-tale-of-myspace-apis.aspx
# re: jQuery AJAX calls to a WCF REST Service
For a more public API I suspect my goal would be to make as much as possible available via GET access because that's usually easier to consume for a variety of clients.
# re: jQuery AJAX calls to a WCF REST Service
I started looking into alternatives to JSON serialization and this post does just that. Now I'll dig into WCF a little deeper.
Thanks!
# re: jQuery AJAX calls to a WCF REST Service
This is the example that's given:
<code lang="javascript">
myData = JSON.parse(text, function (key, value) {
return key.indexOf('date') >= 0 ? new Date(value) : value;
});
</code>
Of course there's nothing wrong with your version, I just thought it was cool they added that functionality in.
# re: jQuery AJAX calls to a WCF REST Service
# re: jQuery AJAX calls to a WCF REST Service
I actually still use my original original JSON (V1) code that I hacked a long time ago. Never had a problem with that either and its considerably lighter.
# re: jQuery AJAX calls to a WCF REST Service
It seems like a REST based approach would use something like: http://app.com/quote/msft
Also, @Adam: can you (or anyone else) shed some light into the shortcomings of ASP.NET AJAX? I ask because I'm about to embark on a project and I'm trying to wrap my head around a REST approach and see what benefits it would offer in developing AJAX enabled applications. I truly get REST for *end users* and it's abundantly clear why having all of your resources uniquely identifiable by URL is a big win, but I'm struggling with REST for developers in AJAX application scenarios.
Also: why bother with jQuery (or any other AJAX library) to make simple data retrieval requests when ASP.NET AJAX does that bit just fine? I'm a bit puzzled by this as well. I can understand wanting to use the utilities and conveniences of a given library, but why shun the default ASP.NET AJAX requests?
Thanks.
# re: jQuery AJAX calls to a WCF REST Service
Here's why I think it matters: If you are using Web Services you will still need to apply the data returned somehow, which means writing DOM and JavaScript code. That's where ASP.NET AJAX falls completely flat providing practically zero value at the moment. So if I want to efficiently write client script code it's more than likely that I will already be using a client library of some sort.
If I do use a client library then WHY SHOULD I bother using ASP.NET AJAX when I can write that same Web Service call code with a few lines of client code? As an advantage I can cut out System.Web.Extensions and the configuration nightmare it introduces, plus 65k+ of client script libraries and I'm not losing anything in terms of functionality. That seems like a win-win situation to me.
It'd be a different story if the Microsoft client library actually had some value on the client, but for your day to day development it provides very little useful features so it's just dead weight (ie. ScriptManager on a page alone will cause the library to load). Further I don't appreciate the design of the client libraries with it's rigid framework APIs that require reams of code to simulate .NET like structure that is IMHO inappropriate for JavaScript.
This is of course my opinion, and maybe it's an extreme view by I'm pragmatic about the tools I use and create - I want things to be easy and reasonably transparent and the current ASP.NET AJAX libraries are anything but.
There are problems with all JavaScript tools, but there's always a path of least resistance and frankly ASP.NET AJAX is not it at least not for me.
As to the REST issue: Yes the example here is more RPC style, but the same approach can be used with a more REST centric interface. There are many different ways that you can call these methods and return data it just so happens that the examples above are more RPC style. But you can still use pure REST based protocol rules and STILL return RPC style messages. There's really a fine line and the semantics can overlap significantly. The difference really lies in what clients are your target audience - if you have an application specific AJAX API most likely you'll tend towards an RPC style mechanism, where a public access API may be more general with query string based input that is easier to access generically without a specific JSON client.
# re: jQuery AJAX calls to a WCF REST Service
nice post, this helped me out a lot getting WCF working with jQuery. I think you can get the best of both worlds - wrapped requests and bare responses by using WebMessageBodyStyle.WrappedRequest. Have you tried this?
# re: jQuery AJAX calls to a WCF REST Service
# re: jQuery AJAX calls to a WCF REST Service
Bare, Wrapped, WrappedRequest and WrappedResponse - if you use WrappedRequest you get a bare Response and if you use WrappedResponse you get a bare request. It makes for a pretty unintuitive API really but unless I am mistaken it gives you all the options you need. I've just got a jQuery call running against a WCF service using a bare request and wrapped response anyway so I'm fairly certain it's working :)
The confusing enumeration is detailed here: http://msdn.microsoft.com/en-us/library/system.servicemodel.web.webmessagebodystyle.aspx
# re: jQuery AJAX calls to a WCF REST Service
Thanks
# re: jQuery AJAX calls to a WCF REST Service
<root>
<Employee id=1>
<name> sam</name>
<age>1</age>
</Employee>
</root>
I want to retrieve the value of id (i.e) 1
# re: jQuery AJAX calls to a WCF REST Service
I'd like to preface by saying that I've long converted to an all client DOM approach to building web UIs over years ago (I haven't written an ASPX page with UI controls and post back in over three years).
You are spot on about the lack of features in the ASP.NET AJAX libraries for DOM support (or perhaps it's just not well documented?) as I have relied on Dojo and prototype to augment the client side libraries for all of my projects.
It was good to see your points articulated (particularly the config...it's a pain to merge with SharePoint configuration, for example). However, I do still believe there is some value in the ASP.NET AJAX client library in that it reduces the amount of custom code required to make the actual calls.
# re: jQuery AJAX calls to a WCF REST Service
-Travis
# re: jQuery AJAX calls to a WCF REST Service
Again, I have a question about something that is M$ related, and your blog satisfies. It seems that my instincts for development always seem to follow yours (albeit, a day late and a dollar short) ;-).
I completely agree w/your comments re:ASP.NET AJAX also. I was so looking forward to it's release, but when it was actually released, and I studied it, I realized what a dog it is. I sometimes think that except for a few folks, Microsoft no longer has very many good architects--too many cluster youknowwhats have come out of there in the last few years.
The combo of ASP.NET/WCF/JQuery is IMO, definitely the way to go. Thanks for the great research and examples.
# re: jQuery AJAX calls to a WCF REST Service
I've discovered a couple of things in my explorations that might be useful to others.
In this I've found that the event log is my friend and can contain some very helpful information.
My test application is in VB so that may differ from C#.
I just moved the .NET framework (but not VS yet) to SP1. A web service compiled under .NET 3.5 pre SP1, failed.
The event log gave me story and I found how to fix it. Recompile and it's good to go. Trouble is there are implications for deployment if the target system is not SP1'ed and you are.
Issue is an assembly called "App_Web_***" which changes name.
Here's an example of the event log details that alert you to this:
WebHost failed to process a request.
Sender Information: System.ServiceModel.ServiceHostingEnvironment+HostingManager/33420276
Exception: System.ServiceModel.ServiceActivationException: The service '/***.svc' cannot be activated due to an exception during compilation. The exception message is: Could not load file or assembly 'App_Web_kt11bzi4, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.. ---> System.IO.FileNotFoundException: Could not load file or assembly 'App_Web_kt11bzi4, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.
File name: 'App_Web_kt11bzi4, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null'
at System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
at System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection)
at System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
at System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection)
at System.Reflection.Assembly.Load(String assemblyString)
at System.ServiceModel.Activation.ServiceHostFactory.CreateServiceHost(String constructorString, Uri[] baseAddresses)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.CreateService(String normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.ActivateService(String normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath)
WRN: Assembly binding logging is turned OFF.
To enable assembly bind failure logging, set the registry value [HKLM\Software\Microsoft\Fusion!EnableLog] (DWORD) to 1.
Note: There is some performance penalty associated with assembly bind failure logging.
To turn this feature off, remove the registry value [HKLM\Software\Microsoft\Fusion!EnableLog].
--- End of inner exception stack trace ---
at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath)
at System.ServiceModel.ServiceHostingEnvironment.EnsureServiceAvailableFast(String relativeVirtualPath)
Process Name: w3wp
Process ID: 4464
For more information, see Help and Support Center at http://go.microsoft.com/fwlink/events.asp.
# re: jQuery AJAX calls to a WCF REST Service
I have tried both forms of JSON string:
"{'fname':'Jimmy', 'lname':'Smith'}" - returned from a custom method and JSON.stringify'ed
"[{'name':'fname', 'value':'Jimmy'},{'name':'lname', 'value':'Smith'}]" - this came from using serializeArray() then JSON.stringify
How do digest either of these sets of data?
[WebMethod]
public string setBMB(string[] result)
{
string ret = result.ToString();
return ret;
}
I've tried strings, objects, hashtables, I just don't know how to get to the data. With the other Web Methods I send a simple {'var':'value'} and reference it with myMethod(string var) and it works fine. How can I do this with this large object with 57 fields?
Thanks!
# re: jQuery AJAX calls to a WCF REST Service
Its a very well written post, and brought most of the positives. I have been following your blog from sometime now and have always benefited from the same.
I have been into WCF REST Service, and am pretty convinced about the usability and effectiveness of the same. I agree that usage of "script manager" is unnecessary heavy and config madness remains. Last September i started to dig into ASP.Net MVC, and i found out jQuery getting used in the same. But i found it to be very raw... and Visual Studio still doesnt support much of it still...
Would you recommend to go with it whenever it comes clean? Am pretty much happy with using REST Services along with jQuery right now. It is performant and less complicated, but somehow i feel maintaining might be a worry. Whats your take on it?
-Wali.
# re: jQuery AJAX calls to a WCF REST Service
http://www.zamd.net/2008/07/08/ErrorHandlingWithWebHttpBindingForAjaxJSON.aspx
# re: jQuery AJAX calls to a WCF REST Service
Do you have an example for calling a WCF service that is not part of your web application but actually running alongside it under a different port in Cassini? The reason I ask is because, thus far I have been unable to get this to work.
I have created a WCF Service called Common in my web application.
I have created the same thing in another WCF Web Service project.
The files look identical with the exception of the namespaces.
This works...
var Proxy = new serviceProxy("/Common.svc/");
This does NOT work...
var Proxy = new serviceProxy("http://localhost:999/Common.svc/");
I have also compared web.config files and both make the same changes to the file, so there is nothing out of the ordinary there either.
If you are unable to reproduce this behavior I would be happy to send you an example. I look forward to your reply.
# re: jQuery AJAX calls to a WCF REST Service
If you're calling 'external' services in this way you need to proxy on the server or use browser hacks (like iFrames or script loading) to make the requests.
# re: jQuery AJAX calls to a WCF REST Service
I am going to try and rethink what I was trying to do here.
I have multiple web sites that do a lot of the same things. I was hoping to create a web service that all of them could call directly from client script rather than having to call back into themselves and then making the call through a proxy.
But if what you are saying is true, I either need to convert all my web applications to go through IIS and forget about Cassini or I need to start setting up proxies...
# re: jQuery AJAX calls to a WCF REST Service
One question though ... As you explained above in response to Chris's question, I am using iframe to host WPFBrowser application (produces xaml page) who is talking to local WCF service. This service is already running on the machine and thats how I want to consume it. So the xaml page is added through iframe on aspx page. I found out that the communication between xaml and aspx page is possible only via cookies or query string. I was wondering if there is any possibility to use JQuery in that senario so that objects can be passed between xaml and aspx.
thanks ...looking forward to your reply.
# re: jQuery AJAX calls to a WCF REST Service
# re: jQuery AJAX calls to a WCF REST Service
Can the data passed to the Ajax method be hierarchical?
My testing indicates no, can you confirm this?
My workaround was to do this:
jQuery.post(createEnergyOfferForm.attr("action"), { myComplexType: JSON2.stringify(_myComplexType) }, function(data) { ... }, "json" );
In an MVC application, "myComplexType" is the form data key, and the string is the value.
# re: jQuery AJAX calls to a WCF REST Service
I'd recommend going the latter route. There are lots of issues you need to deal with like date conversions that are easy to miss if you do the conversion yourself.
# re: jQuery AJAX calls to a WCF REST Service
# re: jQuery AJAX calls to a WCF REST Service
These services expect input parameters as JSON input and traditionally via POST data. You also need to be able to post process the returned JSON result to handle date fixup. The why's are all covered in the post.
# re: jQuery AJAX calls to a WCF REST Service
There's one part of the equation that I'm missing in using JSON for WCF, and that's getting Silverlight to send JSON in its request to a service. So for example, you say in this post about what the input request looks like "on the wire," well how do you force the client (again, I'm using Silverlight) to format its request as JSON? My Googability is failing me!
# re: jQuery AJAX calls to a WCF REST Service
Can't get working complex types as input like pointing here : http://encosia.com/2009/04/07/using-complex-types-to-make-calling-services-less-complex/
The guy use old asmx web service. I tried relatively the same using WCF but can't get things to work. Help!
Thx!
# re: jQuery AJAX calls to a WCF REST Service
if I create date in javascript (like new Date for today) I will have UTC prefix (for example on today Thu Aug 12 9:24:00 UTC+0300 2009). And when transferring to wcf I will receive
time 6.24 (i.e. 9.24-3). All tests was local. SO even without different timezone. On current moment I am thinking about datejs library function setTimezone("GMT"). but it looks like bad hack. how you deal with this issue?
# re: jQuery AJAX calls to a WCF REST Service
Even so, all my code was working...
turns out that IE8 has an instrinsic JSON object based on the code designed by Doug Crockford - and ironically that also appears to suffer from the same problem...
# re: jQuery AJAX calls to a WCF REST Service
http://www.west-wind.com/weblog/posts/729630.aspx
The code in that post should work with json2, and all the native JSON objects.
# re: jQuery AJAX calls to a WCF REST Service
Thanks for all your excellent articles, i really learn a lot from them. Keep it up! :)
I actually wrote an article of my own on how to create a javascript proxy for a webservice:
http://yoavniran.wordpress.com/2009/08/02/creating-a-webservice-proxy-with-jquery/
Yoav.
# re: jQuery AJAX calls to a WCF REST Service
And good job on this well written article.
As with Cris here, I would like to use 'external' web services.
Why? Because I sometimes tend to add features to an existing webside running on a different platform than mine. The easy way out as I can see it would be an 'external' web service I can access from jQuery.
So my question is, how does one create a proxy to do this dirty work?
Regards,
Andreas
# re: jQuery AJAX calls to a WCF REST Service
I do get results without any issue.
Problem arises, when I include the javascript proxy (created by way of ...localhost/TestWCFAjax.svc/jsDebug - and say I named the javascript file as TestWCFAjax.js). I do create a var ServiceProxy = WCFAEService.WCFSearchAE._staticInstance;
Then when I try to test from my test page in my ASP.Net web application, in the onclick javascript handler of a button, the WCF proxy method call seems to be fine, the execution goes through the invoke call and then in the onComplete method, I get a statusCode = 12030 and the corresponding message being Method Not Found. And the failedCallback method gets called and I alert the message accordingly. I did follow the config setting up for AJAX enabled WCF service and I have it as
<system.serviceModel>
<diagnostics wmiProviderEnabled="true">
<messageLogging logMessagesAtServiceLevel="true" logMessagesAtTransportLevel="true" />
</diagnostics>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" />
<!--<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>-->
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="EndpointBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<!--<webHttpBinding>
<binding name="default"/>
</webHttpBinding>-->
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service behaviorConfiguration="serviceBehavior" name="WCFAEService.WCFSearchAE">
<endpoint address="" binding="webHttpBinding"
behaviorConfiguration="EndpointBehavior"
bindingConfiguration=""
contract="WCFAEService.IWCFSearchAE" >
<!--bindingConfiguration="default"
contract="WCFAEService.IWCFSearchAE" >-->
</endpoint>
<!--<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />-->
</service>
</services>
</system.serviceModel>
Any help is greatly appreciated.
# re: jQuery AJAX calls to a WCF REST Service
I am sending xml from jquery ajax method to WCF method replacing all special characters.
my jquery method structure is :
function UpdateUserProfile(UserId ) {
var reqParams = {
LinkedinUrl:$("#hdnProf").val(),
LinkedinFeed:$("#hdnfeed").val()
};
}
var reqParams_Serialized = Sys.Serialization.JavaScriptSerializer.serialize(reqParams);
$.ajax({
url: servicepath + xyz.svc/mydata",
type: 'Post',
processData: false,
contentType: 'application/json;charset=utf-8',
data: reqParams_Serialized,
cache: false,
success: function(response) {
},
failure: function(response) {
}
});
}
Iam getting an Problem . If the length of xml increases jquery method does not make hit to WCF method.
Also this problem occurs for some users xml.
any suggestion or alternative way to send xml.
# re: jQuery AJAX calls to a WCF REST Service
# re: jQuery AJAX calls to a WCF REST Service
I've tried 'filter=Date+eq+(1082678400000)' but had a 500 Internal Server Error.
# re: jQuery AJAX calls to a WCF REST Service
Is webHTTPBinding the only one that works with JQuery? I have a similar JQuery call working on my local machine with Visual Studio 2010 in debug mode, but as soon as I publish it to the server it is asking me to use anonymous access on the site which is not an option. I need to be able to transport the credentials. It seems that WCF has changed drastically even between the Beta and the release of VS2010. I am having trouble finding documentation on all but the most common bindings and how to specify security with them.
# re: jQuery AJAX calls to a WCF REST Service
# re: jQuery AJAX calls to a WCF REST Service
In the passing of two years already they seem to have changed the attributes a bit.
[WebInvoke(UriTemplate = "Customers/{id}/Update", RequestFormat = WebMessageFormat.Json)]
I needed to remove the Method="Post" from the list because oddly enough that did not seem to work anymore. Eventhough it was still in the intellicense.. ?
# re: jQuery AJAX calls to a WCF REST Service
Best post I found till now on Jquery wrapper
but for me it does not work the stringify of dates
I first used ServiceProxy and used firebug to see the result of serialization
it was not in the MS Ajax format just enclosed in double quotes
I included the json2.js from your modified zip file json2_msdates.zip before the ServiceProxy.js
and also put this.isWcf = true; from this.isWcf = false; what I found in your file
Then tried different date formats with the proxy it still does not work
the code var a = reISO.exec(value); returns null all the times
Then tried to use json2 directly and it is not MS AJAX type of serialization
Maybe I did not find your right version of the code?
Very confused :)
not an expert in Java Script so did not try to understand all code
any help apreciated
Best Regards
Dan
# re: jQuery AJAX calls to a WCF REST Service
I figured it out, never mind
Thank you for the post Jquery is great
# not working in IE 6 and IE 7
I initially tested it in IE 8 and was working fine
but it gives me the message 'JSON' is undefined when I test it with IE 6 and 7
the references I have are bellow:
<link href="../App_Themes/Cupertino/jquery-ui-1.8.5.custom.css" rel="stylesheet" type="text/css" />
<script src="../JavaScript/jquery-1.4.1.js" type="text/javascript"></script>
<script src="../JavaScript/jquery-ui-1.8.5.custom.min.js" type="text/javascript"></script>
<script src="../JavaScript/json2.js" type="text/javascript"></script>
<script src="../JavaScript/ServiceProxy.js" type="text/javascript"></script>
the only Jquery code i have is bellow nothing fancy
var proxy = new ServiceProxy("/FunStoreTwo/WcfAjaxServices/ManageEmployee.svc/");
proxy.invoke("GetSupervisors", {}, function (result) {
for (var i = 0; i < result.length; i++) {
var employee = result[i];
var text = employee.FirstName + " " + employee.LastName;
var value = employee.UserId;
$('#ReportsTo').append($('<option></option>').val(value).html(text));
}
},
function (error) {
$('#message').text(error.message);
}
);
====================================================================
Morevover I had a different page where I used $.ajax({}) instead of ServiceProxy and it works in all brosers. As soon as I add a reference to ServiceProxy.js Version 0.97 - 8/31/10
it gets stucked without any message this time (I do not use the library in code only added the reference) these are the only references I added
I Have no ideea how to fix it I wonder oif I took an older version of your ServiceProxy.js or it does not work in IE 6 and 7?
<script src="../JavaScript/jquery-1.4.1.js" type="text/javascript"></script>
<script src="../JavaScript/json2.js" type="text/javascript"></script>
<script src="../JavaScript/ServiceProxy.js" type="text/javascript"></script>
Please help
Thank you
# not working in IE 6 and IE 7
I initially tested it in IE 8 and was working fine
but it gives me the message 'JSON' is undefined when I test it with IE 6 and 7
the references I have are bellow:
<link href="../App_Themes/Cupertino/jquery-ui-1.8.5.custom.css" rel="stylesheet" type="text/css" />
<script src="../JavaScript/jquery-1.4.1.js" type="text/javascript"></script>
<script src="../JavaScript/jquery-ui-1.8.5.custom.min.js" type="text/javascript"></script>
<script src="../JavaScript/json2.js" type="text/javascript"></script>
<script src="../JavaScript/ServiceProxy.js" type="text/javascript"></script>
the only Jquery code i have is bellow nothing fancy
var proxy = new ServiceProxy("/FunStoreTwo/WcfAjaxServices/ManageEmployee.svc/");
proxy.invoke("GetSupervisors", {}, function (result) {
for (var i = 0; i < result.length; i++) {
var employee = result[i];
var text = employee.FirstName + " " + employee.LastName;
var value = employee.UserId;
$('#ReportsTo').append($('<option></option>').val(value).html(text));
}
},
function (error) {
$('#message').text(error.message);
}
);
====================================================================
Morevover I had a different page where I used $.ajax({}) instead of ServiceProxy and it works in all brosers. As soon as I add a reference to ServiceProxy.js Version 0.97 - 8/31/10
it gets stucked without any message this time (I do not use the library in code only added the reference) these are the only references I added
I Have no ideea how to fix it I wonder oif I took an older version of your ServiceProxy.js or it does not work in IE 6 and 7?
<script src="../JavaScript/jquery-1.4.1.js" type="text/javascript"></script>
<script src="../JavaScript/json2.js" type="text/javascript"></script>
<script src="../JavaScript/ServiceProxy.js" type="text/javascript"></script>
Please help
Thank you
# re: jQuery AJAX calls to a WCF REST Service
JSON object should exist in IE 6 when json2.js loads and executes. Reason it works in 8 is that IE 8 includes native JSON object. IE 6 does not and requires the json2.js version.
You'll also want to check for script errors. There might be something else going on preventing json2.js from executing.
# re: jQuery AJAX calls to a WCF REST Service
I may have added another plugin to it or changed something while testing
so started over again
Now it works
Thank you Rick
# re: jQuery AJAX calls to a WCF REST Service
{ date: "\/Date(" + theDate.getTime() + ")\/" }
# re: jQuery AJAX calls to a WCF REST Service
I saw Chris' comment and your response on 2/18/09, and like Chris my objective was to create a client component that could hit a WCF service hosted on a remote server to process data. I was using your example as a guideline, but like Chris I hit a wall when I couldn't hit the WCF service from another site hosted on a different server/port.
Other than setting up a proxy server, are there any other ways around this? Am I utilizing WCF for the incorrect purposes to accomplish my goal? Surely this isn't a unique scenario, so how would you recommend approaching this scenario?
Thanks in advance,
Ben
# re: jQuery AJAX calls to a WCF REST Service
Ben
# re: jQuery AJAX calls to a WCF REST Service
I have one problem if i use jquery version 1.5, it throws an error Unknown error occurred in callback. Any idea why this could be happening?
# re: jQuery AJAX calls to a WCF REST Service
I had this problem today too, and didn't know what had cause it. Apparently, jQuery completely redid the $.ajax() in version 1.5. And did a good job at being backwards compatible, but there were some things they couldn't do.
I'd advise this article:
http://encosia.com/2011/02/02/jquery-1-5s-ajax-rewrite-and-asp-net-services-all-is-well/
He covers what they've changed. If you're using the ServiceProxy.js code provided by Rick, then I had to go in and fix a couple things (I'm using a modified version that handles DateTimes), but it should be the same. And there may be a much better way of doing this, this is just the workaround I found for now.
Find this line:
this.invoke = function (method, params, callback, errorHandler)
Then scroll down to your .ajax(... You'll first notice in version 1.5 they've changed the calling syntax to .ajax(url, settings)...so I simply removed the url from the settings and dropped it into
$.ajax(url, {
type: "POST",
contentType: _I.contentType,
data: jsonData,
dataType: "html",
dataFilter: function (jsonString, type)
{
if (type == "html")
{
// Use json library so we can fix up dates
var res = JSON.parseWithDate(jsonString);
if (res && res.hasOwnProperty("d"))
res = res.d;
return res;
}
return jsonString;
},
success: function (result){...}
error: function (xhr, status){...}
}
});
Hope that helps you out, remember to make sure and use the same success and error functions provided in yours. Also, you might want to make sure your dataFilter is similar to what it was before. But as I said, it will completely ignore dataFilter if your dataType is html, and it appears to not work at all if you don't use a registered parameter.
As Dave said in his posting, "As of jQuery 1.5, using this dataFilter approach for manually controlling deserialization will no longer work if the request’s dataType is set to “json” or even omitted."
Good luck, hopefully that helps! And obviously the $.ajax 1.5 documentation is online at:
http://api.jquery.com/jQuery.ajax/
# re: jQuery AJAX calls to a WCF REST Service
When the service is hosted on another domain the browser first sends an OPTIONS request to validate the Access-Control-Allow-Origin header.
However, when I switch to BodyStyle=WebMessageBodyStyle.Wrapped, the server returns 400 errors (and my server method code is never reached).
How can I resolve this?
Thank you very much for the excellent post!
# re: jQuery AJAX calls to a WCF REST Service
I have followed your posts for a long time, thanks a ton!
I found something that might be a bug in the JSON2.js customization. I couldn't get the .parse function to work with a date string that was generated by the .stringify function. So this date string:
2011-04-11T21:44:14.960Z
Was getting split like by this line of code:
var matches = str.split(/[-,:,T,Z]/);
and winding up with the period between seconds and milliseconds still there, which doesn't work for the conversion to a javascript date variable using the Date.UTC function. Also, after the .join there was still an extra comma at the end. So I also added a .pop to the array if the last piece is an empty string to avoid this. Here is my modified code that works for me:
var matches = str.split(/[-,:,T,Z,.]/);
matches[1] = (parseInt(matches[1], 0) - 1).toString();
if (matches[matches.length - 1].length == 0) {
matches.pop();
}
date = "new Date(Date.UTC(" + matches.join(",") + "))";
My two changes are:
- Added ,. to the split so that the decimal for milliseconds is treated as a split token.
- Added my conditional .pop block.
What do you think? Am I doing something wrong, or did I find a real issue and correctly resolve it?
Many thanks in advance,
# re: jQuery AJAX calls to a WCF REST Service
thanks
# re: jQuery AJAX calls to a WCF REST Service
# re: jQuery AJAX calls to a WCF REST Service
how can i use jquery to call wcf service using custom userNamePasswordValidationMode. i was able to call using asp.net client program but could not do it using jquery. I kept System.Web.Script.Services.ScriptService for service class to enable it to be called from script. I am using wsHttpBinding binding. I want to call this service from jquery to authenticate and fetch data and it should be cross domain calls using jsonp.
Thanks
Pullet
# re: jQuery AJAX calls to a WCF REST Service
Thanks for figuring out the jQuery integration; duly tagged.