1

I have made in .NET a web service method called “Login” and I have published it in my in my localhost(IIS). The method just takes 2 String parameters (Username and Password) checks in a database that I have in my sql server if there is a user that matches these parameters and if it finds someone returns 1, else it returns 0. From my browser it all works fine.

I tried to reach the method by an android app (at first just take the result and show it on the screen). Here is the code (I’ve found many bits from here and there):

public class LoginCheck extends Activity {

    private static final String SOAP_ACTION = "http://tabtobook.org/Login";
    private static final String METHOD_NAME = "Login";
    private static final String NAMESPACE = "http://tabtobook.org/";
    private static final String URL = "http://192.168.1.2/TabBookServices/Users.asmx";
    private TextView tv;

    @Override
    public void onCreate(Bundle savedInstanceState) {
         /** Called when the activity is first created. */
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        tv=(TextView)findViewById(R.id.tv);
        ServiceCall();
    }
    public void ServiceCall()
    {
        try{
        SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
        HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
        String A="user1";
        request.addProperty("Username", A);
        String B="user1";
        request.addProperty("Password", B);

        SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
        envelope.dotNet=true;
        envelope.setOutputSoapObject(request);

        androidHttpTransport.call(SOAP_ACTION, envelope);

         SoapObject result = (SoapObject)envelope.getResponse();
         tv.setText(result.toString());
        }       

        catch (final IOException e)
        {
            ((TextView) findViewById(R.id.tView)).setText("test3");
            e.printStackTrace();

        } catch (final XmlPullParserException e)

        {
            e.printStackTrace();
        } catch (final Exception e)

        {
            e.printStackTrace();
        }
    }
}

From my debugging so far, the program throws the “final Exception e” (the very last on my code) when it goes at the line “androidHttpTransport.call(SOAP_ACTION, envelope);”. From the WSDL I get:

targetNamespace="http://tabtobook.org/", location="http://localhost/TabBookServices/Users.asmx, soapAction="http://tabtobook.org/Login"

(I didn’t copy it all, cause I couldn't do it here for a reason. Anyway at the same web service there are other irrelevant methods) So I think that I got the NAMESPACE, METHOD_NAME, SOAP_ACTION and URL right. But being a newbie in soap I cannot be sure.

So what is wrong? Is the request envelop malformed, or do I use the androidHttpTransport wrong? (Or maybe both!)

EDIT: I put some lines from the logcat. I think it is the "android.os.NetworkOnMainThreadException" that throws the exception. Should I try something like an Asynchtask to handle it?

11-11 21:17:53.607: D/AndroidRuntime(4574): Shutting down VM 11-11 21:17:53.667: I/AndroidRuntime(4574): NOTE: attach of thread 'Binder Thread #3' failed 11-11 21:17:53.667: D/dalvikvm(4574): GC_CONCURRENT freed 102K, 77% free 483K/2048K, paused 1ms+3ms 11-11 21:17:53.667: D/dalvikvm(4574): Debugger has detached; object registry had 1 entries 11-11 21:17:54.117: W/System.err(4491): android.os.NetworkOnMainThreadException 11-11 21:17:54.237: W/System.err(4491): at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1084) 11-11 21:17:54.237: W/System.err(4491): at libcore.io.BlockGuardOs.connect(BlockGuardOs.java:74) 11-11 21:17:54.248: W/System.err(4491): at libcore.io.IoBridge.connectErrno(IoBridge.java:127) 11-11 21:17:54.248: W/System.err(4491): at libcore.io.IoBridge.connect(IoBridge.java:112) 11-11 21:17:54.298: W/System.err(4491): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192) 11-11 21:17:54.298: W/System.err(4491): at java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459) 11-11 21:17:54.298: W/System.err(4491): at java.net.Socket.connect(Socket.java:842) 11-11 21:17:54.307: W/System.err(4491): at libcore.net.http.HttpConnection.(HttpConnection.java:77) 11-11 21:17:54.317: W/System.err(4491): at libcore.net.http.HttpConnection.(HttpConnection.java:50)


I did it using an Asynchtask: (I do not edit the first post so that everyting exists there)

private class DownloadWebPageTask extends AsyncTask<String, Void, String> {

    @Override
    protected String doInBackground(String... urls) {
        String response = "";
        try {

                SoapObject request = new SoapObject(NAMESPACE, METHOD_NAME);
                HttpTransportSE androidHttpTransport = new HttpTransportSE(URL);
                String A="user2";
                request.addProperty("Username", A);
                String B="user2";
                request.addProperty("Password", B);
                SoapSerializationEnvelope envelope = new SoapSerializationEnvelope(SoapEnvelope.VER11);
                envelope.dotNet=true;
                envelope.setOutputSoapObject(request);

                androidHttpTransport.call(SOAP_ACTION, envelope);
                SoapObject result = (SoapObject)envelope.bodyIn; 
                response=result.toString();                     

                }

             catch (Exception e) {
                e.printStackTrace();

            }
        return response;
    }

    @Override
    protected void onPostExecute(String result) {
        tv.setText(result);
    }
}

public void ServiceCall() {
    DownloadWebPageTask task = new DownloadWebPageTask();
    task.execute(); 
    }
}

What I get in my screen is "LoginResponse{LoginResult=1;}" if the the user exists or "LoginResponse{LoginResult=0;}"if he does not. So the method works fine!

Now I have 2 problems to make it a login module as I want (of course I'll search for those):

  1. I need a way to take just the result "0" or "1" from the method. Or I think maybe I could use the whole string. But when I try something like "if(result.equals("LoginResponse{LoginResult=1;}"))" it does not work (it does not get a true value). What is the problem?

  2. I want the user to input the data. So I have to pass arguments to the AsyncTask. Is that possible? Or should I do the reading of the input (setting listener on a button), inside the AsyncTask class?

EDIT: for number 2 I found the answer here -> Android: How can I pass parameters to AsyncTask's onPreExecute()?

EDIT: for number 1 what was missing was just a space!

if(result.equals("LoginResponse{LoginResult=1; }"))

works fine! I'd like to know how to get the just the methods result (0 or 1) though. If someone knows please answer!

Community
  • 1
  • 1
george
  • 1,386
  • 5
  • 22
  • 38
  • Can you post the exception / stack trace from logcat? – Torid Nov 11 '11 at 18:25
  • hmmm.. Now I see a NetworkOnMainThreadException in the logcat. Of course the programm does not stop. So, does that mean that I should put the androidHttpTransport.call(SOAP_ACTION, envelope); command inside a different thread? Or in an asynchronous task? – george Nov 11 '11 at 21:22
  • I think the AsyncTask is a good way to go... I have an app that does a series of HTTP GETs/POSTs where things can change along the way (dependingon what the app gets back etc.). Each Request/Response is in a AsyncTask doInBackground() which then sets up flags for onPostExecute() - which then either reports to the user or kicks off the next Request/Response in a new AsyncTask. The nice thing is that a very variable sequence of 10-20 messages you need hardly any state - everything is driven one step at a time. – Torid Nov 16 '11 at 07:43
  • well it is a nice way for sure and everything I do works great till now. But is it really required? Not one of the examples or tutorials I've seen around uses an asynctask to call a soap webservice!? So did I have some other mistake in my first approach or what? – george Nov 17 '11 at 00:32

1 Answers1

0

Please provide more information about how you setup your Dot.Net service. In particular the type of binding you are using and the version of Dot.Net framework you are employing.

The best approach when using Dot.Net WCF services in a heterogeneous client environment is to build yourself a simple Java client to consume the service to ensure that the bindings and security configuration on your WCF stack is setup in an open manner that can be consumed by other technologies. For example, in WCF 4.0 every binding type except for basicHttpBinding provides user authentication and transfer security which requires the client to be functionally compatible.

Once you have proven out the heterogeneous Java client you will have a better understanding of what you need to do for other non WCF clients as well.

Along the same line of thinking, also try to consume your WCF service using SoapUI. It is a Java tool and achieves the same goal of proving out your service in a heterogeneous environment.

cmdematos
  • 883
  • 4
  • 12
  • 24
  • Well it is a soap service and noy a WFC service. I think that can be seen from the Users.asmx suffix. Anyway, as I wrote below I was able to consume it so the problem was not on the service type. Thank you for your reply though, it's been informative! – george Nov 12 '11 at 11:08