Contributor: JonRanes

Prototype Cross Site Ajax With WCF

Last month RSC took on a project to deliver category search to a classic asp at MegaHobby.com.  They use MonsterCommerce and are unable to edit the server code on their site.  I said, "I know, we can use Ajax".  I wasn't 100% sure it would work but I wanted to try.  There was the issue of it having to be cross site as there was no way to host the service under their domain name.  Also it would have to perform well as they have several thousand products to search through several fields.

The basic problem was a general search on their site for say "boat" would return 1291 results.

megah-old

Well, suppose you were only looking for Aircraft Model Kits, Army Men and Playsets, Aviation Replicas, Balsa Airplanes or Books, or DVD and Videos that contained the word "boat" specifically.  It would be a lot of going from page to page of results, waiting for the entire page to render and never knowing if the next page was going to have your desired category.  The client had already categorized their products but the ecommerce program they use had no way of implementing this in the search.  So the goal was to make the search look like this.

megah-new

First off was to set up a WCF service to handle the client script results.  I would want the service to return standard Json data with no special .NET formatting as I had no control over the display of the data other than what I could do with a client script library.  If you are doing something like this for the first time there are a few names you should get to know.  The first is Rick Strahl, Rick seems to have the practical answers to most WCF questions, answers from experience and not a book.  The second is Carlos Figueira and his article showing how to coax WCF to send back raw stream data.  You know Json the way the normal world does it, without all the tags quotes and junk.  Basically you set the return type of the WCF service as System.IO.Stream.

[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest,
        ResponseFormat = WebMessageFormat.Json
        )] 
System.IO.Stream AllCategories(string sCatName);

[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.WrappedRequest,
        ResponseFormat = WebMessageFormat.Json
        )]
System.IO.Stream GetProducts(string sCatName, string sSearch);

And then to convert my Linq data to to Json was so simple I was amazed.

var CatWProds = db.SearchCategoryProductCnt(sCatName, dPrice);

JavaScriptSerializer jss = new JavaScriptSerializer();
string result = jss.Serialize(CatWProds).ToString();
result = "getResponse(" + result + ");";
byte[] resultBytes = Encoding.UTF8.GetBytes(result);
WebOperationContext.Current.OutgoingResponse.ContentType = "text/plain";
return new MemoryStream(resultBytes);

The JavaScriptSerializer is found under System.Web.Script.Serialization and it takes my var result to a Linq call to a search based stored procedure that joins a fulltexttable to a view and poof, converts it to awesome raw Json in what two lines of code.  You can also see above I am implementing JsonP with this line.

result = "getResponse(" + result + ");";

The next big blog post that really helped me and many others out is Consume WCF Using AJAX Without ASP.NET by Alik Levin.  I would recommend reading that article and running the sample code yourself as I am sure it will come in handy at some point.

So now I was ready to code the client end of this application.  My main consideration was how to achieve a cross site Ajax call that was cross browser compatible.  Enter Thierry Schellenbach  with the cross site Prototype library plug-in.  This plug-in is fully tested in ie, ff, and safari and others.  I was starting to get nervous I wouldn't be able to pull this off until I found Thierry's plug-in.  I added a little really simple history and was creating tables on the client in just a few lines of code.

function CallService(sSearch) {
    url = 'http://localhost/wcf2ajax/service.svc/ajaxEndpoint/AllCategories?time='
    url += new Date().getTime().toString(); // prevent caching            
    $('product_result').innerHTML = "";
    new Ajax.Request(url, {
        method: 'GET',
        crossSite: true,
        parameters: { "sCatName": sSearch },
        onLoading: function(transport) {
        },
        onSuccess: function(transport) {
        },
        onFailure: function(transport) {
        }
    });
}

function getResponse(json) {
    if (json !=null){ 
        var data = json;
        var close = "</a> | ";
        var bodyFormatted = "";
        if (data.length > 0) {
            for (var i = 0; i < data.length; i++) {
                var item = data[i];
                var sCatName = item.CatName.replace(/'/g, "");
          

Being able get to data in JavaScript using notation like item.CatName is a real plus.  Json is really great.  Setting the browser history and page title with RSH isn't much harder than.

dhtmlHistory.add("#hSearchTerm:" + ajst);
ChangeTitle("MegaHobby.com Search for: " + ajst);
dhtmlHistory.initialize();
dhtmlHistory.addListener(yourListener);

So if you have clients locked into a platform needing new features cross site Ajax may be a viable solution.

Head over to MegaHobby.com and search around for Star Trek and see what this approach can do.

Comments

refreshcmnts
(gravatar only)
Edit Comment

Please wait... loading

Reply To Comment

Please wait... loading

 
Powered By: MvcCms