MonoAndroid:使用 dotnet Web 服务(ASMX)
在您的移动应用程序中使用 ASMX Web 服务。
引言
我再次带着我的 **MonoAndroid** 系列文章回来了,上一篇文章请参阅底部。在这篇文章中,我将演示如何在移动应用程序中使用 ASMX Web 服务(非 WCF)。
Web 服务正日益成为移动和 Web 应用程序的集成部分。Mono Android 支持几乎所有类型的 Web 服务,如 *Restful*、*WCF* 和常规的 *SOAP Web 服务*。在这篇文章中,我将创建一个基于 dotnet 的 Web 服务,并在我的移动应用程序中进行消费。
在这篇文章中,我将创建一个**软件开发人员层级**应用程序。在这个应用程序中,我们将创建一个 dotnet Web 服务,提供一个 Web 方法,该方法将发送具有其职务的软件人员列表,并在我们的 Android 移动 ListView 中显示它们。
我们将一步一步进行。
- 选择 **New ->Solutions** 来创建 Android 应用程序,并将其命名为“
MonoWebService
”。
图 1:创建Android项目! -
现在,默认情况下,当您在 Android 中创建项目时,它会包含一个按钮。因此,应用程序流程将是:在点击按钮时,我们将调用 Web 服务并用检索到的数据填充 ListView。
因此,按钮文本包含*“Hello World”*,当我们检查按钮属性时,它会显示它引用的是字符串资源,这意味着按钮标签来自字符串表。
现在要更改按钮上的文本,您需要修改 **Resources\values** 下的 *strings.xml*。只需查找名为“hello”的行,然后将其更改为“Retrieve Data from Web service”。请看我用粗体标记的行。
<?xml version="1.0" encoding="utf-8"?> <resources> <string name="hello">Retrieve Data from Web service</string> <string name="app_name">MonoWebService</string> </resources>
- 现在,在 *MainActivity* 文件中添加 **ListView**,添加后,UI 代码看起来是这样的:-
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:id="@+id/myButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> <ListView android:minWidth="25px" android:minHeight="25px" android:layout_width="fill_parent" android:layout_height="match_parent" android:id="@+id/Main_ListView" /> </LinearLayout>
-
现在是时候在 Visual Studio 2010 中创建 Web 服务了。现在打开*“Create New Project”*,将 .Net framework 3.5 更改为使 **ASP.NET Web Service Application project** 可供选择。
现在以*“MonoAndroidWebService“*为名创建项目。
-
现在将默认的
Service1
名称更改为MonoDataService
,并删除其他任何内容。现在添加GetWebServiceMonoDatas()
方法,该方法返回硬编码的 WebServiceMonoData 列表。public class MonoDataService : System.Web.Services.WebService { [WebMethod] public List<WebServiceMonoData> GetWebServiceMonoDatas() { var lstFragmentDemo = new List<WebServiceMonoData> { new WebServiceMonoData() { Name = "Alok Gupta", Desigination = "Snr Software Engineer" }, new WebServiceMonoData() { Name = "Jasdeep Singh", Desigination = "Snr Auditor (Information)" }, new WebServiceMonoData() { Name = "Ashish Srivastava", Desigination = "Software Test Engineer" }, new WebServiceMonoData() { Name = "Hariharan Ramchandran", Desigination = "Product Architect" } }; return lstFragmentDemo; } }
现在,以下是 *WebServiceMonoData* 类的代码。
[Serializable] public class WebServiceMonoData { public string Name { get; set; } public string Desigination { get; set; } }
由于我们通过 HTTP 在服务之间发送类,因此我们需要使我们的类**可序列化**。构建和编译 Web 服务,以便它可以用于创建 Web 引用。
-
现在,在您的移动应用程序中,右键单击 **Project->Add-> Add Web Reference**,请看我在下面的截图中标记了它。
将 Web 服务 URL 更改为您的本地服务地址,在我的情况下是 **“https://:61847/MonoDataService.asmx”**。选择 framework .Net 2.0 web services,并将引用命名为“**MonoDataService**”。
- 现在,在 MainActivity 文件中添加以下代码,我将在稍后解释。
public class MainActivity : Activity { protected override void OnCreate (Bundle bundle) { base.OnCreate (bundle); // Set our view from the "main" layout resource SetContentView (Resource.Layout.Main); Button button = FindViewById<Button> (Resource.Id.myButton); button.Click += OnWebserviceRetrievedInformation; } void OnWebserviceRetrievedInformation (object sender, EventArgs e) { var objMonoAndroidService = new MonoDataService.MonoDataService (); objMonoAndroidService.BeginGetWebServiceMonoDatas (WebServiceCallBack, objMonoAndroidService); } void WebServiceCallBack (IAsyncResult ar) { var objMonoAndroidService = ar.AsyncState as MonoDataService.MonoDataService; var arrWebServiceMonoDatas = objMonoAndroidService.EndGetWebServiceMonoDatas (ar); var lstWebServiceMonoData = new List<MonoWebService.MonoDataService.WebServiceMonoData>(arrWebServiceMonoDatas); var mainListView = FindViewById<ListView>(Resource.Id.Main_ListView); mainListView.Adapter = new ListBaseAdapter (this, lstWebServiceMonoData); } }
上面我们正在做以下事情:- 在按钮点击时,创建 **MonoDataService.MonoDataService** 对象,并异步调用 GetWebServiceMonoDatas 方法。
- 在回调函数中,从检索到的数组创建 **WebServiceMonoData** 列表,并将其传递给我们的自定义适配器来创建 **ListView**。以下是我们自定义的、派生自 **BaseAadapter** 的类的代码。
public class ListBaseAdapter: BaseAdapter<WebServiceMonoData> { List<MonoWebService.MonoDataService.WebServiceMonoData> _lstWebServiceMonoData; Activity _mainActivity; public ListBaseAdapter (Activity mainActivity, List<MonoWebService.MonoDataService.WebServiceMonoData> lstWebServiceMonoData) { _lstWebServiceMonoData = lstWebServiceMonoData; _mainActivity = mainActivity; } #region implemented abstract members of BaseAdapter public override long GetItemId (int position) { return position; } public override View GetView (int position, View convertView, ViewGroup parent) { var item = this [position]; if (convertView == null) convertView = _mainActivity.LayoutInflater.Inflate (Android.Resource.Layout.SimpleListItem2, parent, false); convertView.FindViewById<TextView> (Android.Resource.Id.Text1).Text = item.Name; convertView.FindViewById<TextView> (Android.Resource.Id.Text2).Text = item.Desigination; return convertView; } public override int Count { get { return _lstWebServiceMonoData== null? -1: _lstWebServiceMonoData.Count; } } #endregion #region implemented abstract members of BaseAdapter public override WebServiceMonoData this [int index] { get { return _lstWebServiceMonoData== null? null: _lstWebServiceMonoData[index]; } } #endregion }
您可以 在此处 了解有关创建自定义 Base Adapter 的更多信息。
-
现在构建并运行您的移动应用程序,您将看到这个丑陋的异常弹出:-
问题在于,您的移动应用程序正在尝试在本地移动设备上查找 Web 服务,但它并不存在,因为它存在于开发机器上。现在,要从模拟器访问 Web 服务,您需要使用魔法 IP 地址 10.0.2.2,而不是 LocalHost。现在,在创建 Web 服务对象时,请像这样传递 URL:-
void OnWebserviceRetrievedInformation (object sender, EventArgs e) { var objMonoAndroidService = new MonoDataService.MonoDataService ("http://10.0.2.2:61847/MonoDataService.asmx"); objMonoAndroidService.BeginGetWebServiceMonoDatas (WebServiceCallBack, objMonoAndroidService); }
-
再次尝试构建并运行移动应用程序,您会再次遇到异常,这次是因为从工作线程更新 UI 控件。
现在要解决这个问题,请将这两行代码移到 WebServiceCallBack 方法中的
RunOnUiThread
下,如下所示:-RunOnUiThread (() => { var mainListView = FindViewById<ListView> (Resource.Id.Main_ListView); mainListView.Adapter = new ListBaseAdapter (this, lstWebServiceMonoData); });
- 现在构建并运行应用程序,
4 英寸屏幕上 按钮点击时
魔法 IP 表
本节文字摘自 这里,逐字逐句。
每个实例的虚拟路由器管理 10.0.2/24 网络地址空间 — 由路由器管理的所有地址的形式为 10.0.2.<xx>,其中 <xx> 是一个数字。此空间内的地址由模拟器/路由器预分配如下:
网络地址 | 描述 |
10.0.2.1 | 路由器/网关地址 |
10.0.2.2 | 指向您的主机回环接口的特殊别名(即,在您的开发机器上为 127.0.0.1) |
10.0.2.3 | 第一个 DNS 服务器 |
10.0.2.4 / 10.0.2.5 / 10.0.2.6 | 可选的第二个、第三个和第四个 DNS 服务器(如果有) |
10.0.2.15 | 模拟设备自身的网络/以太网接口 |
127.0.0.1 | 模拟设备自身的回环接口 |
关注点
我使用了MonoAndroid (C#)和Xamarin Studio来构建本教程。请留意,如果我继续学习,您可能会期待更多文章即将发布。
尽管Xamarin Studio是专有软件,但他们提供了免费的入门版本来构建、测试和发布Android应用程序。我正在使用它来学习。
本系列文章!
- MonoAndroid:用 C# 编写自定义通用 BaseAdapter
- MonoAndroid:在您的移动应用程序中使用 GridView
- MonoAndroid:在移动应用程序中使用 TabHost
- MonoAndroid:在移动应用中使用 Fragments
- MonoAndroid:使用 Started Service
- MonoAndroid:调用次级活动
- MonoAndroid:用 C# 编写 ExpandableListView 和 BaseExpandableListAdapter
- MonoAndroid:使用 AlertDialog
本系列技巧/窍门
历史
- 2013 年 8 月 22 日:初版
- 2013 年 9 月 6 日:更新了技巧和窍门部分
- 2013 年 10 月 10 日:更新了技巧和窍门部分
- 2013 年 11 月 4 日:更新了文章系列
- 2013年11月22日:更新了其他文章部分