如何用Retrofit调用ASP.NET WebService?解决Android调用baseUrl错误
关于Retrofit调用ASP.NET WebService的问题解答
一、先解决你遇到的「baseUrl must end in /」错误
这个错误其实是Retrofit的硬性要求,同时你的baseUrl写法也有问题,我给你拆解一下:
错误原因
- Retrofit要求baseUrl必须以斜杠
/结尾:它会自动拼接baseUrl和接口注解里的路径,如果baseUrl没结尾斜杠,拼接逻辑会出错,所以直接抛出这个提示。 - 你的baseUrl包含了查询参数:
http://192.138.0.100/Client.asmx?op=Client_Login里的?op=Client_Login属于请求参数,不该放在baseUrl里,baseUrl应该是固定的根地址,不能带动态参数或查询串。
修正步骤
- 修改baseUrl为正确格式:
把你的baseUrl改成以下两种之一(选适合你的):// 方式1:根域名结尾带斜杠 private static String BASE_URL = "http://192.138.0.100/"; // 方式2:指向你的asmx接口文件,结尾带斜杠 private static String BASE_URL = "http://192.138.0.100/Client.asmx/"; - 调整你的ApiInterface接口:
因为你要调用的是Client_Login方法,正确的写法应该把op=Client_Login作为查询参数,或者直接指定到方法路径。举个规范的例子:public interface ApiInterface { // 方式1:通过@Query指定op参数 @GET("Client.asmx") Call<Login> authenticate( @Query("op") String operation, @Query("MobileNo") String mobileNo, @Query("Pass") String password, @Query("AppVer") String appVer ); // 方式2:直接把方法名写在路径里(如果你的WebService支持这种REST风格) @GET("Client.asmx/Client_Login") Call<Login> authenticate( @Query("MobileNo") String mobileNo, @Query("Pass") String password, @Query("AppVer") String appVer ); } - 调用接口时传对参数:
如果用方式1,调用时要传"Client_Login"作为operation参数:Call<Login> call = apiService.authenticate("Client_Login", "你的手机号", "你的密码", "1.0");
二、完整的Retrofit调用ASP.NET WebService步骤
如果是第一次用Retrofit调用这类接口,我给你梳理下完整流程:
1. 添加Retrofit依赖
在你的Module级build.gradle里添加依赖(版本可以选最新的):
implementation 'com.squareup.retrofit2:retrofit:2.9.0' // 如果用Gson解析返回的JSON数据,加这个 implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
2. 创建数据模型类
根据你的WebService返回的JSON结构,创建对应的实体类,比如Login类:
public class Login { private boolean success; private String message; private UserInfo userInfo; // 生成getter、setter方法,或者用Lombok简化 }
3. 定义Retrofit接口
分两种情况,看你的WebService是REST风格还是SOAP风格:
情况1:REST风格的asmx接口
就是我们刚才修正的那种写法,用@GET/@POST配合@Query传递参数。
情况2:SOAP风格的WebService
如果你的WebService是传统SOAP接口,需要构造SOAP请求体:
public interface SoapApiInterface { @POST("Client.asmx") @Headers({ "Content-Type: text/xml; charset=utf-8", "SOAPAction: \"http://你的命名空间/Client_Login\"" // 替换成你WebService的命名空间 }) Call<ResponseBody> login(@Body String soapEnvelope); }
然后构造SOAP请求字符串:
public String buildSoapRequest(String mobileNo, String password, String appVer) { return "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">" + "<soap:Body>" + "<Client_Login xmlns=\"http://你的命名空间/\">" + "<MobileNo>" + mobileNo + "</MobileNo>" + "<Pass>" + password + "</Pass>" + "<AppVer>" + appVer + "</AppVer>" + "</Client_Login>" + "</soap:Body>" + "</soap:Envelope>"; }
4. 初始化Retrofit实例
Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) // JSON解析用,SOAP可以不用 .build(); // 创建接口实例 ApiInterface apiService = retrofit.create(ApiInterface.class);
5. 发起网络请求
注意:Android里网络请求不能在主线程,所以要用enqueue异步回调,或者用协程、RxJava:
Call<Login> call = apiService.authenticate("Client_Login", "13800138000", "123456", "1.0"); call.enqueue(new Callback<Login>() { @Override public void onResponse(Call<Login> call, Response<Login> response) { if (response.isSuccessful()) { Login result = response.body(); // 这里处理成功返回的结果 if (result.isSuccess()) { // 登录成功逻辑 } else { // 登录失败,提示message } } else { // 服务器返回错误码,比如404、500 Log.e("Retrofit", "请求失败:" + response.code()); } } @Override public void onFailure(Call<Login> call, Throwable t) { // 网络失败,比如无网、连接超时 Log.e("Retrofit", "网络错误:" + t.getMessage()); } });
内容的提问来源于stack exchange,提问作者bhoomika patel
相关产品推荐
相关产品推荐

