【问题标题】:Difficulty in making a soap request to a .NET web service from an android app难以从 Android 应用程序向 .NET Web 服务发出肥皂请求
【发布时间】:2011-12-27 04:41:18
【问题描述】:

我在 .NET 中创建了一个名为“Login”的 Web 服务方法,并在我的 localhost(IIS) 中发布了它。该方法只需要 2 个字符串参数(用户名和密码)检查我在我的 sql 服务器中拥有的数据库是否存在与这些参数匹配的用户并且如果它发现有人返回 1,否则它返回 0。从我的浏览器这一切工作正常。

我尝试通过一个 android 应用程序访问该方法(起初只是获取结果并将其显示在屏幕上)。这是代码(我从这里和那里找到了很多位):

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();
        }
    }
}

到目前为止,从我的调试来看,程序在“androidHttpTransport.call(SOAP_ACTION,envelope);”行处抛出“final Exception e”(我的代码中的最后一个)。从我得到的 WSDL:

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

(我没有全部复制,因为我在这里做不到是有原因的。反正在同一个Web服务中还有其他不相关的方法) 所以我认为我得到了正确的 NAMESPACE、METHOD_NAME、SOAP_ACTION 和 URL。但作为肥皂的新手,我不能确定。

那么有什么问题吗?是请求信封格式错误,还是我使用了 androidHttpTransport 错误? (或者两者兼而有之!)

编辑:我从 logcat 中放了一些行。我认为引发异常的是“android.os.NetworkOnMainThreadException”。我应该尝试像 Asynchtask 之类的东西来处理它吗?

11-11 21:17:53.607:D/AndroidRuntime(4574):关闭 VM 11-11 21:17:53.667:I/AndroidRuntime(4574):注意:附加线程 'Binder Thread #3' 失败 11-11 21:17:53.667: D/dalvikvm(4574): GC_CONCURRENT 释放 102K,77% 释放 483K/2048K,暂停 1ms+3ms 11-11 21:17:53.667: D/dalvikvm(4574): 调试器已分离;对象注册表有 1 个条目 11-11 21:17:54.117: W/System.err(4491): android.os.NetworkOnMainThreadException 11-11 21:17:54.237: W/System.err(4491): 在 android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1084) 11-11 21:17:54.237: W/System.err(4491): 在 libcore.io.BlockGuardOs.connect(BlockGuardOs.java:74) 11-11 21:17:54.248: W/System.err(4491): 在 libcore.io.IoBridge.connectErrno(IoBridge.java:127) 11-11 21:17:54.248: W/System.err(4491): 在 libcore.io.IoBridge.connect(IoBridge.java:112) 11-11 21:17:54.298: W/System.err(4491): 在 java.net.PlainSocketImpl.connect(PlainSocketImpl.java:192) 11-11 21:17:54.298: W/System.err(4491): 在 java.net.PlainSocketImpl.connect(PlainSocketImpl.java:459) 11-11 21:17:54.298: W/System.err(4491): 在 java.net.Socket.connect(Socket.java:842) 11-11 21:17:54.307: W/System.err(4491): 在 libcore.net.http.HttpConnection.(HttpConnection.java:77) 11-11 21:17:54.317: W/System.err(4491): 在 libcore.net.http.HttpConnection.(HttpConnection.java:50)


我使用的是异步任务: (我没有编辑第一篇文章,所以一切都在那里)

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(); 
    }
}

如果用户存在,我在屏幕上看到的是“LoginResponse{LoginResult=1;}”,如果用户不存在,则为“LoginResponse{LoginResult=0;}”。所以方法很好用!

现在我有两个问题要让它成为我想要的登录模块(当然我会搜索那些):

  1. 我需要一种从方法中获取结果“0”或“1”的方法。或者我想也许我可以使用整个字符串。但是当我尝试“if(result.equals("LoginResponse{LoginResult=1;}"))”之类的东西时,它不起作用(它没有得到真正的值)。有什么问题?

  2. 我希望用户输入数据。所以我必须将参数传递给 AsyncTask。那可能吗?还是应该在 AsyncTask 类中读取输入(在按钮上设置监听器)?

编辑: 对于 2 号,我在这里找到了答案 -> Android: How can I pass parameters to AsyncTask's onPreExecute()?

编辑: 对于数字 1,缺少的只是一个空格!

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

工作正常!我想知道如何获得方法结果(0 或 1)。如果有人知道请回答!

【问题讨论】:

  • 你能从 logcat 发布异常/堆栈跟踪吗?
  • hmmm.. 现在我在 logcat 中看到了 NetworkOnMainThreadException。当然程序不会停止。那么,这是否意味着我应该把 androidHttpTransport.call(SOAP_ACTION, envelope);命令在不同的线程中?还是在异步任务中?
  • 我认为 AsyncTask 是一个很好的方法......我有一个应用程序可以执行一系列 HTTP GET/POST,其中事情可能会在此过程中发生变化(取决于应用程序返回的内容等。 )。每个请求/响应都在 AsyncTask doInBackground() 中,然后为 onPostExecute() 设置标志 - 然后向用户报告或在新的 AsyncTask 中启动下一个请求/响应。好消息是 10 到 20 条消息的可变序列几乎不需要任何状态 - 一切都是一步一步驱动的。
  • 嗯,这肯定是一个不错的方法,我所做的一切都很好,直到现在。但真的需要吗?我见过的示例或教程中没有一个使用异步任务来调用肥皂网络服务!?那么我在第一种方法中是否还有其他错误?

标签: android .net web-services soap wsdl


【解决方案1】:

请提供有关如何设置 Dot.Net 服务的更多信息。特别是您使用的绑定类型和您使用的 Dot.Net 框架版本。

在异构客户端环境中使用 Dot.Net WCF 服务的最佳方法是自己构建一个简单的 Java 客户端来使用该服务,以确保 WCF 堆栈上的绑定和安全配置以开放的方式设置,可以被其他技术消耗。例如,在 WCF 4.0 中,除了 basicHttpBinding 之外的所有绑定类型都提供用户身份验证和传输安全性,这要求客户端在功能上兼容。

一旦您证明了异构 Java 客户端,您将更好地了解您还需要为其他非 WCF 客户端做什么。

按照同样的思路,也可以尝试使用 SoapUI 来使用 WCF 服务。它是一种 Java 工具,可实现在异构环境中验证服务的相同目标。

【讨论】:

  • 嗯,这是一项肥皂服务,而不是 WFC 服务。我想这可以从 Users.asmx 后缀中看出。无论如何,正如我在下面写的那样,我能够使用它,所以问题不在于服务类型。感谢您的回复,它提供了丰富的信息!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-21
  • 2012-05-07
  • 1970-01-01
  • 2016-04-11
  • 2023-01-31
  • 2017-01-06
相关资源
最近更新 更多