65.9K
CodeProject 正在变化。 阅读更多。
Home

MonoAndroid:使用 dotnet Web 服务(ASMX)

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.90/5 (10投票s)

2013年8月22日

CPOL

5分钟阅读

viewsIcon

67337

downloadIcon

2441

在您的移动应用程序中使用 ASMX Web 服务。

引言

我再次带着我的 **MonoAndroid** 系列文章回来了,上一篇文章请参阅底部。在这篇文章中,我将演示如何在移动应用程序中使用 ASMX Web 服务(非 WCF)。

Web 服务正日益成为移动和 Web 应用程序的集成部分。Mono Android 支持几乎所有类型的 Web 服务,如 *Restful*、*WCF* 和常规的 *SOAP Web 服务*。在这篇文章中,我将创建一个基于 dotnet 的 Web 服务,并在我的移动应用程序中进行消费。

在这篇文章中,我将创建一个**软件开发人员层级**应用程序。在这个应用程序中,我们将创建一个 dotnet Web 服务,提供一个 Web 方法,该方法将发送具有其职务的软件人员列表,并在我们的 Android 移动 ListView 中显示它们。

我们将一步一步进行。

  1. 选择 **New ->Solutions** 来创建 Android 应用程序,并将其命名为“MonoWebService”。



    图 1:创建Android项目!
     
  2.  
  3. 现在,默认情况下,当您在 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>
    

  4. 现在,在 *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>                                
    
  5. 现在是时候在 Visual Studio 2010 中创建 Web 服务了。现在打开*“Create New Project”*,将 .Net framework 3.5 更改为使 **ASP.NET Web Service Application project** 可供选择。

     

    现在以*“MonoAndroidWebService“*为名创建项目。

  6. 现在将默认的 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 引用。

  7. 现在,在您的移动应用程序中,右键单击 **Project->Add-> Add Web Reference**,请看我在下面的截图中标记了它。

     

    将 Web 服务 URL 更改为您的本地服务地址,在我的情况下是 **“https://:61847/MonoDataService.asmx”**。选择 framework .Net 2.0 web services,并将引用命名为“**MonoDataService**”。

     

  8. 现在,在 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 的更多信息。

  9. 现在构建并运行您的移动应用程序,您将看到这个丑陋的异常弹出:- 

     

    问题在于,您的移动应用程序正在尝试在本地移动设备上查找 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);
    }
    
  10. 再次尝试构建并运行移动应用程序,您会再次遇到异常,这次是因为从工作线程更新 UI 控件。

     

    现在要解决这个问题,请将这两行代码移到 WebServiceCallBack 方法中的 RunOnUiThread 下,如下所示:-

    RunOnUiThread (() => {
    	var mainListView = FindViewById<ListView> (Resource.Id.Main_ListView);
    	mainListView.Adapter = new ListBaseAdapter (this, lstWebServiceMonoData);
    });
    
  11. 现在构建并运行应用程序,
    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应用程序。我正在使用它来学习。

本系列文章!

本系列技巧/窍门  

历史  

  • 2013 年 8 月 22 日:初版
  • 2013 年 9 月 6 日:更新了技巧和窍门部分 
  • 2013 年 10 月 10 日:更新了技巧和窍门部分 
  • 2013 年 11 月 4 日:更新了文章系列 
  • 2013年11月22日:更新了其他文章部分
© . All rights reserved.