Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Web and WebWorks Development

Reply
BlackBerry Development Advisor
tneil
Posts: 3,702
Registered: ‎10-16-2008
My Carrier: Rogers

How "I" would call a web service from a WebWorks App[Example Included]

[ Edited ]

Hi Everyone,

 

I've participated in a bunch of threads around calling web services from widgets.  A bunch of these threads have been around ASP.NET.  So I figured I would create a post showing how I would go about writing a web service written in ASP.NET that I would then access from my Widget.

 

To start off with, I figured I would create an example where I had an existing ASP.NET web service that I wanted to extend to mobile.  The first rule of thumb is that SOAP web services are INCREDIBLY BLOATED with tons of mark-up and syntax that you typically don't need.  It was designed with server to server data transfer via a wired connection in mind.

 

This becomes especially apparent in the mobile world as you are going to have to process all of that bloat on the client and then transform it into something meaningful.  What I like to do is create some small wrapper methods on an existing web service interfaces so that it can continue to be used by those who want to call the pre-existing methods directly via SOAP, but also have an additional much more efficient mobile friendly JSON interface.  This allows me the ability to provide a nice end result without ever having to change any logic from my existing web service interfaces.

 

While my examples below are shown in ASP.NET (because I'm a .NET junkie), the same principals can be applied to all web services written in any language.

 

Looking at JSON

 

JSON can be your best friend when it comes to bringing back data.  Basically once JSON is parsed it becomes a JavaScript object.  You can look at it as built in deserialization from a string.

 

There are a TON of JSON parsers out there for pretty much any language you can think of.  For details on all the available parsers take a look at http://json.org/

 

For my example I chose the JavaScript JSON toolkit from http://code.google.com/p/json-sans-eval/.  In BlackBerry 6, JSON parsing will be built in, but on 5.0 you need a little toolkit.  For my server side I just created the JSON syntax myself manually, but there are toolkits for that as well.

 

web.config

 

<system.web>
  <webServices>
    <protocols>
      <add name="HttpSoap"/>
      <add name="HttpGet"/>
    </protocols>
  </webServices>
......

 If you are wanting to pass down parameters via POST and GET you will need to enable these protocols for your ASP.NET web service.  They were turned off by default starting with .NET framework 2.0

 

 

My server side code:

 

using System;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Linq;
using System.Xml.Serialization;

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
    public Service () { }

    [WebMethod]
    public Car GetCar(String make, String model) 
    {
        Car car = new Car();
        car.Make = make;
        car.Model = model;
        car.Year = 2002;
        return car;
    }

    [WebMethod]
    public String GetCarJSON(String make, String model)
    {
        return GetCar(make, model).toJSON();
    } 
}

public class Car : Object
{
    public String Make = String.Empty;
    public String Model = String.Empty;
    public int Year = 0;

    public String toJSON()
    {
        String result = "{" +
            "\"Make\": \"" + this.Make + "\", " +
            "\"Model\": \"" + this.Model + "\", " +
            "\"Year\": \"" + this.Year + "\"" +
            "}";
        return result;
    }
}

 

 

You will see that I created a GetCarJSON() companion method that acts as a quick wrapper around the main GetCar() method that was previously exposed.  This gives my mobile a nice alternative method to call that will then return JSON instead of SOAP XML.  You can entirely re-use your existing methods without change.

 

To complete this simplification, I added a toJSON() method on my Car object.  This will then serialize the object into its JSON representation.  

 

NOTE: Please forgive my code "casing" between C# and JavaScript... I have too many languages running around in my head  :smileyhappy:

 

Now let's look at the Client side code:

 

 

<html>
  <head>
    <meta name="viewport" id="viewport" content="initial-scale=1.0,user-scalable=no" />
    <script type="text/javascript" src="json_sans_eval.js"></script>
    <script type="text/javascript">
      var xmlHttp = new XMLHttpRequest();
		    
      function doClick() {
        var url = "http://localhost:4100/service/service.asmx/GetCarJSON?make=Subaru&model=WRX";
        xmlHttp.open('GET', url, true);
        xmlHttp.onreadystatechange = callbackFunction;
        xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
        document.getElementById('results').innerHTML = "Requesting...";
        xmlHttp.send(null);
      }
		    
      function callbackFunction(){
        if (xmlHttp.readyState != 4) 
          return;

        var result = xmlHttp.responseXML.documentElement;
        var jsonString = result.childNodes[0].nodeValue;
              
        // I used the JSON parser found here http://code.google.com/p/json-sans-eval/
        var car = jsonParse(jsonString); 
              
        var innerHTML = "<div><b>Make:</b>" + car.Make + "</div>\n" +
                        "<div><b>Model:</b>" + car.Model + "</div>\n" + 
                        "<div><b>Year:</b>" + car.Year + "</div>\n";
              
        document.getElementById('results').innerHTML = innerHTML;
      }           
    </script>
  </head>
  <body>
    <button onclick="doClick()">Get Single Object</button>
    <div id="results"></div>
  </body>
</html>

 Here I make a simple XMLHttpRequest to the URL for the GetCarJSON() function.  Since the results being returned are well formed XML I can then retrieve the contents of the results from the responseXML property of the XHR object.  From there I grab the contents of my JSON string from the first child node.

 

Here is where the JSON parser comes in.. simply call jsonParse() and my string is now a Car JavaScript object that I can interact with.  JSON allows for all kinds of data structures so that you can replicate pretty much any object you wish to return.

 

Passing down objects to your web service from the client is simply the same process in reverse.

 

 

 

What if you don't have access to the web service source?

 

My recommendation is that if you have an existing SOAP web service that you wish to call and you do not have access to changing its source code, that you should create a small server side wrapper around this web service and provide your JSON data back out of your own web service.

 

This allows for two main benefits:

1) Light weight JSON data going to-and-from your mobile application

2) A layer of abstraction between a Web Service interface that you do not control and your mobile application.  Should this 3rd party interface change, you can abstract those changes away from your mobile client.

 

 

Even More Optimized!

 

You can even take this further by returning <div> statements from your web service instead of JSON.  This is particularly good if you are returning data that is simply for display and does not need to be manipulated in code.  You can then simply dump in the <div> using the innerHTML of an element and not have to do any client side processing.  Since it is returned as a <div> with no formatting, you can then apply a client side CSS to layout the data as you see fit.

 

 

Summary

 

Web services can be really easy to access via a Widget.  There's no need for complicated Java extensions or other heavy options.  Hopefully you will find this information useful and possibly help you out of a bind :smileyhappy:

Tim Neil
Director, Application Platform & Tools Product Management
Follow me on Twitter
Please use plain text.
New Developer
Ekey
Posts: 53
Registered: ‎06-14-2010
My Carrier: None

Re: How "I" would call a web service from a Widget [Example Included]

I am curious if you have tested this with a live web service, rather than just local?

Please use plain text.
Contributor
giridhar_bhandekar
Posts: 39
Registered: ‎04-20-2010
My Carrier: what is this.

Re: How "I" would call a web service from a Widget [Example Included]

Hi TNEIL,

 

        The below approach works fine only with webservices on LOCALHOST alone. Let us know the \

 

approach for the webservice hosted on an server/Remote machine.

 

   Tried with several approaches

 

1) webservice behaviour : webservice.HTC.  BB doesnot support this it seems as initial callservice

 

method gives error stating UNDEFINED function.

 

2) vth JQUERY :   doesnot run even with localhost 

 

Let us know the way ahead .....

 

Quite frustrating and cant help out saying BB not dat much convenient for DOTNET developers :smileysad:

 

Regards

 

GIRI

 

 

Please use plain text.
BlackBerry Development Advisor
tneil
Posts: 3,702
Registered: ‎10-16-2008
My Carrier: Rogers

Re: How "I" would call a web service from a Widget [Example Included]

Hi Ekey, GIRI

 

Yes this method works fine both on localhost and on a remote machine.  

 

JQUERY is an entirely different story, it has both UI capabilities and other convenience methods.  I'm not sure what its webservice toolkit is doing on top of .NET or how you may be using it.

 

What I have personally found is that the "extra bits" that .NET and JQuery place on top of calling a web service as shown above create a level of abstraction but there are lots of places where things can go wrong.

 

You should litterally be able to copy and paste my code from above and it will work.  I have tried it several times without fail on both local and remote resources.  I've always favored going direct and simple where I know exactly what I am calling instead of an abstract toolkit.  Especially when a user's data fees are involved.  I don't want to be doing excessive data requests where it could cost my customer real out of pocket money.

 

Accessing localhost with the BB simulators can sometimes have issues depending on your PC's environment.  This is due to using MDS that serves as the connection proxy.  We are working on ways to eliminate MDS out of the picture for developers for exactly these reasons.

Tim Neil
Director, Application Platform & Tools Product Management
Follow me on Twitter
Please use plain text.
New Developer
Ekey
Posts: 53
Registered: ‎06-14-2010
My Carrier: None

Re: How "I" would call a web service from a Widget [Example Included]

As you may see in my "Utterly baffled" post, I have been able to successfully create JSON using the ideas from your example (with a little research on how to embed multiple "objects" within the JSON, some nice examples on building the array here: http://www.ibm.com/developerworks/library/wa-ajaxintro10/ ). My JSON wrapper takes a dataset with 2 tables and creates an array, sending back a string. It does appear that possibly because it is a .Net method, the BB does not like the returned packet. I'm still not sure where to find those "lots of places where things may go wrong", but I'll pick that up in the other post.

Please use plain text.
New Developer
Ekey
Posts: 53
Registered: ‎06-14-2010
My Carrier: None

Re: How "I" would call a web service from a Widget [Example Included]

In the hope that someone may see something obscure that is wrong with my code, here is how my web service class is setup. You'll notice that this differs slightly from your web service.

 

Imports System.Web.Services 
Imports System.Web.Services.Protocols 
Imports System.ComponentModel 
Imports System.Data.SqlClient 
Imports System.IO 
Imports System.Xml 

<System.Web.Script.Services.ScriptService()> _
<System.Web.Services.WebService(Namespace:=
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<ToolboxItem("http://tempuri.org/")> _False)> _ 
Public Class Service1Inherits System.Web.Services.WebService
....

 

Please use plain text.
New Developer
Ekey
Posts: 53
Registered: ‎06-14-2010
My Carrier: None

Re: How "I" would call a web service from a Widget [Example Included]

I now have the jSON web method working correctly. The params being passed had whitespace. There are a few tidbits I learned along the way however:

 

1. When building the jSON object, do not forget to add the "," after each row;

2. the json_sans_eval.js file DOES contain an eval() method (go figure) but does NOT contain the method reference in the original post (jsonParse);

3. You'll want to use the responseXML.documentElement instead of the responseText because you'll need to get the json from childNode[0].nodeValue

4. Once you can successfully parse your jSON, it's pretty cool being able to use those as objects instead of just "nodes"!

Please use plain text.
Visitor
jfroman
Posts: 1
Registered: ‎10-14-2010

Re: How "I" would call a web service from a Widget [Example Included]

Hi Tim I new in black berry widgets development , i have made a little application that connects with a webserver made in  .Net 2008 and it works fine. But i haven seen any example about how can I POST data from a widget to process that data in the webservice and finally to send back a response to the widget.

 

So if you could provide me an example about how could i POST data to a webservice  from a widget made in VisualStudio.net 2008  That would help me a lot.

 

 

Thanks in advance! 

 

Hello form Saltillo (City),Coahuila (state) Mexico (country)

 

OS: Windows XP SP3

 

Please use plain text.
New Contributor
sharshabel
Posts: 2
Registered: ‎10-31-2010

Re: How "I" would call a web service from a Widget [Example Included]

When I try the example and change the web service to return an HTML, it doesn't work as expected :smileysad: what I get in the screen is the HTML itself (including the tags).

 

Any ideas?

Please use plain text.
Developer
jmace
Posts: 482
Registered: ‎10-24-2008
My Carrier: AT&T

Re: How "I" would call a web service from a Widget [Example Included]

Sharshabel, 

 

try running the following on your client side when you receive the HTML back from the web service.

 

 

...
xmlHTTP.onreadystatechange = function() {
  if (xmlHTTP.readyState == 4) {
    var temp = xmlHTTP.responseText;
    temp = temp.replace(/&lt;/g,"<").replace(/&gt;/g,">");
    document.getElementById('contentDiv').innerHTML = temp;
  }
}
...

 

 

_________________________________________
www.jasonmace.com/blackberry
Please use plain text.