C# Web Service接口开发

sunaichao

贡献于2012-06-18

字数:16460 关键词: WEB服务/RPC/SOA C#

Microsoft .NET体系结构中非常强调Web Service,构建Web Service接口对.NET Framework开发工具有很大的吸引力,因此很多讲建立Web Service机制的文章都是使用.NET Framework开发工具的。   在这篇文章中我们将谈论下面几个方面的问题   1、客户端怎样和Web Service通信的   2、使用已存在的Web Service创建代理对象   3、创建客户端。这包括:     Web 浏览器客户端     Windows应用程序客户端     WAP客户端   最好的学习方法是建立一个基于真实世界的实例。我们将使用一个已存在的Web Service,这个Web Service从纳斯达克获得股票价格,客户端有一个简单的接口,该接口的外观和感觉集中了建立接口的多数语句。   客户端描述   三种客户端都接受客户输入的同一股票代码,如果请求成功,将显示公司名和股票价格,如果代码不可用,将显示一个错误信息。客户端都设置有"Get Quote" 和 "Reset"按钮以初始化用户的请求。   开发中的注意事项   我使用visual studio.NET作为我的集成开发环境,beta版没有结合.NET Mobile Web,因此,我们需要使用文本编辑器创建wap客户端,下一个版本的visual studio.NET将整合入.NET Mobile Web 。   客户端怎样与Web Service通讯   我们先复习一下Web Service的功能,在我得上一篇文章中曾展示一幅图(如图一),a点的用户将通过Internet执行远程调用调用b点web 服务器上的东西,这次通讯由SOAP和HTTP完成。   我们实际执行了b 点web 服务器上的方法吗?对于新手来说这是一个关键问题,由此你可以想到一系列的安全威胁,作为系统管理员我们不可能让随便什么人使用我们的web资源,让怀有恶意的人破坏敏感数据,而且也不能不提到带宽问题。我们还记得这是一个分布式应用程序,因此我们还不得不关心数据的配置。   为解决这些问题,我们需要复制在用户web 服务器上的对象行为,在我们的例子中,我们需要复制b点Web Service针对a点的功能,这就意味着我们要创建充当原始web servcie行为的代理对象(proxy object),这个代理对象象原始Web Service那样具有所有的数据接口。那么我们怎样得到公共数据接口的呢?   各位是否还记得Web Service代码中的关键字Web only,每一个Web only的方法都会被复制到代理对象中,这样将保护我们的敏感数据,避免受到来自Web Service终端(比如:b点 )的有恶意的黑客的攻击。这种方法我们称为在a、b之间进行的"对象数据同步交换",这一过程称为创建"对象代理".   现在看看图1的修正版,如下图:   代理对象是Web Service的基础慨念,所以创建Web Service的第一步是创建代理对象,然后我们可以通过多种平台(Web浏览器, WAP, Personal Digital Assistant [PDA], SOAP客户端)从代理对象获得数据。 创建代理Web Service对象   在.NET Framework中携带了一个创建代理对象的工具"WebServiceUtil.exe",在MS_DOS快捷窗口使用这个工具创建代理对象。   语法如下: WebServiceUtil /c:proxy /pa:HTTP://yourDomain/someFolder/        yourWebService.asmx?SDL /c:proxy 指示编译器创建一个代理对象 /pa:<WebServerURL> 找到sdl文件的路径,最后面的"?SDL"目的是使Web Service获得SDL订约   上面的是必须要的参数,现在解释一下其他重要参数: /disco:<FileName> 创建一个Discovery文件,对不知道精确的url地址的用户而言,Discovery文件是找到Web Service的机制之一。它是一个提供Web Service的简要说明的xml文件,visual studio.NET工程将自动创建一个缺省的Discovery文件作为新工程的一部分,也可以启动"Dynamic Discovery"自动跟踪, /l:<Language Code> 语言可以是C#,Visual Basic或者jscript等,如:/l:Csharp. /n:<Namespace> 该类所在的名字空间。该名字空间的所有类均可访问这个代理对象。 /o:<Location> 表示放置创建的文件的位置。缺省为现行目录。 /i:<Namespace> 附加的名字空间,该名字空间是将输入该类的名字空间。 /protocol: <protocol Name> 应用的协议,如: SOAP, HTTP GET或 HTTP POST。 缺省值为:SOAP   下图是一个创建代理对象的例子   这个命令在当前目录下创建了一个叫LiveQuote.cs的文件。这是一个在WebServiceClients名字空间中的C#文件,当你创建客户端时,将认识到WebServiceClients名字空间的重要性。现在编译C#类,便产生了一个连接客户端工程的DLL文件。,将其置于"bin" 目录下。   这样就在bin目录下创建了一个叫LiveQuotes.dll的文件。如果想了解有关编译c#类的情况可以参考.NET SDK帮助文档。   用这两个命令创建了一个代理对象,现在我们准备从Web Service获得数据。代理对象具有所有的公共接口,可访问任何商业逻辑函数,我们甚至不需要注册DLL文件就可以办到。我们只需要编译源代码并插入bin目录下的dll文件即可。这一切对于Web 服务器访问DLL文件足够了。   如果你不熟悉ASP.NET的配置机制你也许会感到困惑,不注册dll文件是为了让操作系统验证它。我们仅将它放在bin目录下.NET Framework在运行时将带上它。   现在我们创建客户端,创建一个客户端的步骤是:    1、创建一个代理对象的实例    2、在代理对象上执行方法调用    3、捕获从Web Service返回的xml格式的数据    4、写一个特殊的客户端控件显示结果 创建Web 页客户端   Web服务监听器监听HTTP GET, HTTP POST和SOAP 方法调用。首先我们用Visual Studio.NET创建一个Web 工程   打开new project对话框,在project type栏选择visual c# project,在template栏中选择web application,创建一个新工程并在默认的web服务器下创建一个虚拟目录LiveQuotes_Clients,系统同时在DriveName/wwwroot目录下创建一个相同名字的物理目录。   2)右击工程的"References",在弹出的菜单中单击add References   点击"project"选项,导航到代理对象DLL   3)使用Toolbox Web form controls创建asp.NET文件,如果你学过vb,那么这是一件非常轻松的工作。   我将默认文件名WebForm1.aspx修改为Client_WebForm_POST.aspx,当我向web 窗体插入控件时,后台自动在一个叫Client_WebForm_POST.cs的文件中生成c#代码,当引用dll文件时,我们希望系统能自动插入相关代码,但是它没有这样做,这是vs.NET试用版的一个小故障,我们需要手工输入下面这行代码以访问WebServiceClients名字空间。    using WebServiceClients;   代理对象livequotes.DLL属于WebServiceClients名字空间,因此我们需要通过代码访问WebServiceClients名字空间,我们还需要写一些代码处理用户交互事件,比如点击按钮: public void btn_GetQuote_Click (object sender, System.EventArgs e) {  LiveQuotes ProxyLiveQuotes = new LiveQuotes();  try   {    label_PriceValue.Text =            ProxyLiveQuotes.MSNGetLastQuote            (txt_CompanyCode.Text).ToString();    label_NameValue.Text =            ProxyLiveQuotes.MSNGetCompanyName            (txt_CompanyCode.Text).ToString();   }  catch   {    label_PriceValue.Text = "0.0";    label_NameValue.Text = "The Company data is not available";   } } public void btn_Reset_Click (object sender, System.EventArgs e) {  label_PriceValue.Text = "0.0";  label_NameValue.Text = " "; }   完整的代码见附录1,由于可能输入错误的公司代码,因此我们用try..catch捕获错误并处理例外。   4)点击Debug -> Start开始编译代码并显示浏览器   现在我们验证一下,输入一个公司代码,可以看到返回了公司名和股票价格。   默认情况下Visual Studio.NET使用Get方法,不过可以修改html表单属性 将"method = POST" 改为 "method = GET"即可 客户端为windows应用程序   用Visual Studio.NET为Web Service创建一个Windows应用程序客户端也非常容易,按照一下步骤即可:   1)打开New Project窗口,在Project Type栏选择Visual C#,在Templates框中选择Windows Application   2)右击References,在弹出的菜单中点击Add Reference   3)点击.NET References"添加 "System.Web.Services.dll,引入控制台和Web 客户服务是一个好的编程习惯。   4)点击"Project",把LiveQuotes.dll作为一个引用加入工程。   5)现在该为应用程序创建窗体了,从左面的工具箱中拖放控件(如:标签,按钮等),visual studio.NET将在后台自动生成c#代码。我们仅仅需要输入处理用户事件的代码即可。  (完整的代码见附录2) protected void btn_GetQuote_Click (object sender, System.EventArgs e) {  LiveQuotes windowsClient = new LiveQuotes();  try  {   label_PriceValue.Text =       windowsClient.MSNGetLastQuote       (txt_CompanyCode.Text).ToString();   label_Name.Text =       windowsClient.MSNGetCompanyName       (txt_CompanyCode.Text).ToString();  }  catch  {   label_PriceValue.Text = "0.0";   label_Name.Text = "The Company data is not available";  } } protected void btn_Reset_Click (object sender, System.EventArgs e) {  txt_CompanyCode.Text = "";  label_Name.Text = "";  label_PriceValue.Text = ""; }   6)编译、执行客户端程序( visual studio.NET 的Debug -> Start )   7)验证一下,输入公司代码,你将得到公司名和来自NASDAQ的股票价格   这段程序代码创建了一个代理对象,利用SOAP通过HTTP调用远程对象的函数调用,使用try..catch捕获非法的公司代码,并使应用程序转入错误处理。  构建WAP客户端   传统的wap使用纯无限标记语言(wml)编写,.NET Mobile SDK 使我们能够利用象asp.NET控件那样的东西设计wap接口,这样做比写wml脚本快得多。   每一个.NET可移动页面的开始都要加上下面的语句 <%@ Page Inherits="System.Mobile.UI.MobilePage" Language="C#" %> <%@ Register TagPrefix="Mobile" Namespace="System.Mobile.UI" %>   同样我们还是要访问livequotes.dll <%@ Import Namespace = "WebServiceClients" @%>   下面是完整的代码 <%@ Page Inherits="System.Mobile.UI.MobilePage" Language="C#" %> <%@ Register TagPrefix="Mobile" Namespace="System.Mobile.UI" %> <%@ Import Namespace="WebServiceClients" %> <script runat="server" language="c#"> protected void GetQuoteCommand_OnClick(Object sender, EventArgs e) { LiveQuotes ProxyLiveQuotes = new LiveQuotes(); try { Code.Text = "Company Code - " + CompanyCode.Text; CompanyName.Text = "Name - " + ProxyLiveQuotes.MSNGetCompanyName(CompanyCode.Text); Price.Text = "Price - " + ProxyLiveQuotes.MSNGetLastQuote(CompanyCode.Text); } catch { Code.Text = "Company Code - " + CompanyCode.Text; CompanyName.Text = "Name - The company data is not available"; Price.Text = "Price - " + "0.0"; } ActiveForm = SecondForm; } </script> <Mobile:Form runat="server"> <Mobile:Label runat="server">Enter the Company Code:</Mobile:Label> <Mobile:TextBox runat="server" id="CompanyCode" /> <Mobile:Command runat="server" OnClick="GetQuoteCommand_OnClick" Text="Get Quote" /> </Mobile:Form> <Mobile:Form runat="server" id="SecondForm"> <Mobile:Label runat="server" id="Code" /> <Mobile:Label runat="server" id="CompanyName" /> <Mobile:Label runat="server" id="Price" /> </Mobile:Form>   微软 .NET Mobile Web SDK 具有将IE 作为WAP客户端的能力,这将加速开发过程。我使用IE5.5模拟下面的WAP功能。   在点击Get Quote按钮后,将得到下面的页面   对所有的怀疑者而言,下面是一个熟悉的页面   我们已经讨论了构建Web Service的基础,我们通过PDA和SOAP客户端打开了通往Web Service的道路。   结束语   本文集中讨论了微软的web服务,微软不是这个市场的唯一玩家,ibm和sun也都在为抢占市场份额拼命努力,下面ibm和sun 关于Web Service的站点    IBM -- HTTP://www-106.ibm.com/developerworks/webservices/    Sun -- HTTP://www.sun.com/software/sunone/portfolio/aws.html   研究Web Service时非常有兴趣的一件事,这个慨念已经叫嚷很久了,主要厂商都宣布支持Web Service, 但是时间将告诉我们,我们究竟能从这项技术获得些什么。 2.附录1   2.1 Web 客户端代码   Client_WebForm_POST.aspx <%@ Page language="c#" Codebehind="Client_WebForm_POST.cs" AutoEventWireup="false" Inherits="LiveQuotes_Clients.WebForm1" %> <html><head>  <meta name="GENERATOR" Content="Microsoft Visual Studio 7.0">  <meta name="CODE_LANGUAGE" Content="C#"></head> <body> <form method="post" runat="server" name="webServiceForm">  <table cellspacing=1 width=400 border=0>  <tr>   <td style="WIDTH: 16px; HEIGHT: 48px" bgcolor=#ffcc99>    <font style="BACKGROUND-COLOR: #ffcc99"           color=#ffcc99>    </font>   </td>   <td style="WIDTH: 161px; HEIGHT: 48px">    <font style="BACKGROUND-COLOR: #ffcc99"           face=Verdana size=2>    <strong>Web browser </strong></font></td>   <td style="HEIGHT: 48px">    <font style="BACKGROUND-COLOR: #ffcc99">    <font face=Verdana size=2>    <strong>Client</strong>    </font>    </font>   </td>  </tr>  <tr>   <td style="WIDTH: 16px" bgcolor=#ffcc99>    <font face=Verdana color=#ffcc99></font></td>   <td style="WIDTH: 161px">    <asp:Label id=lable_CompanyCode runat="server"       font-names="Verdana" font-size="Smaller">     Company Code    </asp:Label>    <font face=Verdana></font></td>   <td>    <asp:TextBox id=txt_CompanyCode runat="server"       font-names="Verdana" font-size="Smaller">    </asp:TextBox>    <font face=Verdana></font></td></tr>  <tr>   <td style="WIDTH: 16px; HEIGHT: 30px" bgcolor=#ffcc99>   </td>   <td style="WIDTH: 161px; HEIGHT: 30px">    <asp:Label id=label_Name runat="server" Width="102"       Height="18" font-names="Verdana"       font-size="Smaller">     Company Name    </asp:Label>   </td>   <td style="HEIGHT: 30px">    <asp:Label id=label_NameValue runat="server"       font-names="Verdana" font-size="Smaller">    </asp:Label>   </td>  </tr>  <tr>   <td style="WIDTH: 16px; HEIGHT: 26px" bgcolor=#ffcc99>   </td>   <td style="WIDTH: 161px; HEIGHT: 26px">    <asp:Label id=label_Price runat="server"      font-names="Verdana" font-size="Smaller">     Price    </asp:Label>   </td>   <td style="HEIGHT: 26px">    <asp:Label id=label_PriceValue runat="server"        font-names="Verdana" font-size="Smaller">      0.0    </asp:Label>   </td>  </tr>  <tr>   <td style="WIDTH: 16px" bgcolor=#ffcc99></td>   <td style="WIDTH: 161px"></td>   <td></td></tr>  <tr>   <td style="WIDTH: 16px" bgcolor=#ffcc99></td>   <td style="WIDTH: 161px">   <asp:Button id=btn_Reset runat="server" Text="Reset">   </asp:Button></td>   <td>    <asp:Button id=btn_GetQuote runat="server"       Text="Get Quote ">    </asp:Button></td></tr></table> </form> <p> </p> <p> </p> <p> </p> </body></html>   2.1.2 Client_WebForm_POST.cs namespace LiveQuotes_Clients {  using System;  using System.Collections;  using System.ComponentModel;  using System.Data;  using System.Drawing;  using System.Web;  using System.Web.SessionState;  using System.Web.UI;  using System.Web.UI.WebControls;  using System.Web.UI.HtmlControls;  using WebServiceClients;  /// <summary>  /// Summary description for WebForm1.  /// </summary>  public class WebForm1 : System.Web.UI.Page  {   protected System.Web.UI.WebControls.Button btn_GetQuote;   protected System.Web.UI.WebControls.Button btn_Reset;   protected System.Web.UI.WebControls.Label label_PriceValue;   protected System.Web.UI.WebControls.Label label_Price;   protected System.Web.UI.WebControls.Label label_NameValue;   protected System.Web.UI.WebControls.Label label_Name;   protected System.Web.UI.WebControls.TextBox txt_CompanyCode;   protected System.Web.UI.WebControls.Label lable_CompanyCode;   public WebForm1()   {    Page.Init += new System.EventHandler(Page_Init);   }   protected void Page_Load(object sender, EventArgs e)   {    if (!IsPostBack)    {     file://     // Evals true first time browser hits the page     file://    }   }   protected void Page_Init(object sender, EventArgs e)   {    file://    // CODEGEN: This call is required by the ASP+ Windows Form Designer.    file://    InitializeComponent();   }   /// <summary>   /// Required method for Designer support - do not modify   /// the contents of this method with the code editor.   /// </summary>   private void InitializeComponent()   {    btn_GetQuote.Click += new System.EventHandler              (this.btn_GetQuote_Click);    btn_Reset.Click += new System.EventHandler (this.btn_Reset_Click);    this.Load += new System.EventHandler (this.Page_Load);   }   public void DropDownList1_SelectedIndexChanged (object sender, System.EventArgs e)   {   }   public void btn_GetQuote_Click (object sender, System.EventArgs e)   {    LiveQuotes ProxyLiveQuotes = new LiveQuotes();    try    {     label_PriceValue.Text =    ProxyLiveQuotes.MSNGetLastQuote(txt_CompanyCode.Text).ToString();     label_NameValue.Text =    ProxyLiveQuotes.MSNGetCompanyName(txt_CompanyCode.Text).ToString();    }    catch    {     label_PriceValue.Text = "0.0";     label_NameValue.Text = "The Company data is not available";    }   }   public void btn_Reset_Click (object sender, System.EventArgs e)   {     label_PriceValue.Text = "0.0";    label_NameValue.Text = " ";   }  } } 3.附录2   3.1 Windows Application 客户端代码 namespace ClientCSharpApp {  using System;  using System.Drawing;  using System.Collections;  using System.ComponentModel;  using System.WinForms;  using System.Data;    /// <summary>  /// Summary description for Form1.  /// </summary>  public class Form1 : System.WinForms.Form  {   /// <summary>   /// Required designer variable.   /// </summary>   private System.ComponentModel.Container components;   private System.WinForms.Label label_PriceValue;   private System.WinForms.Label label_Name;   private System.WinForms.Button btn_Reset;   private System.WinForms.Label label_CompanyName;   private System.WinForms.Label label_Price;   private System.WinForms.Label label_CompanyCode;   private System.WinForms.TextBox txt_CompanyCode;   private System.WinForms.Button btn_GetQuote;   public Form1()   {    file://    // Required for Windows Form Designer support    file://    InitializeComponent();      file://   // TODO: Add any constructor code after InitializeComponent call file://   }   /// <summary>   /// Clean up any resources being used.   /// </summary>   public override void Dispose()   {    base.Dispose();    components.Dispose();   }   /// <summary>   /// Required method for Designer support - do not modify   /// the contents of this method with the code editor.   /// </summary>   private void InitializeComponent()   {    this.components = new System.ComponentModel.Container ();    this.label_Name = new System.WinForms.Label ();    this.txt_CompanyCode = new System.WinForms.TextBox ();    this.label_Price = new System.WinForms.Label ();    this.label_CompanyName = new System.WinForms.Label ();    this.label_PriceValue = new System.WinForms.Label ();    this.btn_GetQuote = new System.WinForms.Button ();    this.btn_Reset = new System.WinForms.Button ();    this.label_CompanyCode = new System.WinForms.Label ();    file://@this.TrayHeight = 0;    file://@this.TrayLargeIcon = false;    file://@this.TrayAutoArrange = true;    label_Name.Location = new System.Drawing.Point (168, 64);    label_Name.Size = new System.Drawing.Size (288, 24);    label_Name.TabIndex = 6;    txt_CompanyCode.Location = new System.Drawing.Point (168, 32);    txt_CompanyCode.TabIndex = 1;    txt_CompanyCode.Size = new System.Drawing.Size (100, 20);    label_Price.Location = new System.Drawing.Point (24, 112);    label_Price.Text = "Current Price";    label_Price.Size = new System.Drawing.Size (100, 23);    label_Price.Font = new System.Drawing.Font ("Verdana", 8);    label_Price.TabIndex = 3;    label_CompanyName.Location = new System.Drawing.Point (24, 72);    label_CompanyName.Text = "Company Name";    label_CompanyName.Size = new System.Drawing.Size (100, 23);    label_CompanyName.Font = new System.Drawing.Font ("Verdana", 8);    label_CompanyName.TabIndex = 4;    label_PriceValue.Location = new System.Drawing.Point (168, 112);    label_PriceValue.Size = new System.Drawing.Size (100, 23);    label_PriceValue.TabIndex = 7;    btn_GetQuote.Location = new System.Drawing.Point (360, 152);    btn_GetQuote.Size = new System.Drawing.Size (88, 23);    btn_GetQuote.TabIndex = 0;    btn_GetQuote.Font = new System.Drawing.Font ("Arial Black", 8);    btn_GetQuote.Text = "Get Quote";    btn_GetQuote.Click += new System.EventHandler (this.btn_GetQuote_Click);    btn_Reset.Location = new System.Drawing.Point (160, 152);    btn_Reset.Size = new System.Drawing.Size (75, 23);    btn_Reset.TabIndex = 5;    btn_Reset.Font = new System.Drawing.Font ("Arial Black", 8);    btn_Reset.Text = "Reset";    btn_Reset.Click += new System.EventHandler (this.btn_Reset_Click);    label_CompanyCode.Location = new System.Drawing.Point (24, 32);    label_CompanyCode.Text = "Company Code";    label_CompanyCode.Size = new System.Drawing.Size (100, 23);    label_CompanyCode.Font = new System.Drawing.Font ("Verdana", 8);    label_CompanyCode.TabIndex = 2;    this.Text = "Live Quotes C# Client App";    this.AutoScaleBaseSize = new System.Drawing.Size (5, 13);    this.BackColor = System.Drawing.SystemColors.ControlLightLight;    this.ClientSize = new System.Drawing.Size (472, 189);    this.Click += new System.EventHandler (this.Form1_Click);    this.Controls.Add (this.label_PriceValue);    this.Controls.Add (this.label_Name);    this.Controls.Add (this.btn_Reset);    this.Controls.Add (this.label_CompanyName);    this.Controls.Add (this.label_Price);    this.Controls.Add (this.label_CompanyCode);    this.Controls.Add (this.txt_CompanyCode);    this.Controls.Add (this.btn_GetQuote);   }   protected void Form1_Click (object sender, System.EventArgs e)   {   }   protected void btn_GetQuote_Click (object sender, System.EventArgs e)   {    LiveQuotes windowsClient = new LiveQuotes();    try    {     label_PriceValue.Text =         windowsClient.MSNGetLastQuote(txt_CompanyCode.Text).ToString();     label_Name.Text =     windowsClient.MSNGetCompanyName(txt_CompanyCode.Text).ToString();    }    catch    {     label_PriceValue.Text = "0.0";     label_Name.Text = "The Company data is not available";    }   }   protected void btn_Reset_Click (object sender, System.EventArgs e)   {    txt_CompanyCode.Text = "";    label_Name.Text = "";    label_PriceValue.Text = "";   }   /// <summary>   /// The main entry point for the application.   /// </summary>   public static void Main(string[] args)   {    Application.Run(new Form1());   }  } } 4. 附录3   4.1 WAP 客户端 <%@ Page Inherits="System.Mobile.UI.MobilePage" Language="C#" %> <%@ Register TagPrefix="Mobile" Namespace="System.Mobile.UI" %> <%@ Import Namespace="WebServiceClients" %> <script runat="server" language="c#"> protected void GetQuoteCommand_OnClick(Object sender, EventArgs e) {  LiveQuotes ProxyLiveQuotes = new LiveQuotes();  try  {   Code.Text = "Company Code - " + CompanyCode.Text;   CompanyName.Text = "Name - " +      ProxyLiveQuotes.MSNGetCompanyName(CompanyCode.Text);   Price.Text = "Price - " +      ProxyLiveQuotes.MSNGetLastQuote(CompanyCode.Text);   }  catch  {   Code.Text = "Company Code - " + CompanyCode.Text;   CompanyName.Text = "Name - The company data is not available";   Price.Text = "Price - " + "0.0";  }  ActiveForm = SecondForm; } </script> <Mobile:Form runat="server"> <Mobile:Label runat="server">    Enter the Company Code: </Mobile:Label> <Mobile:TextBox runat="server" id="CompanyCode" /> <Mobile:Command runat="server"    OnClick="GetQuoteCommand_OnClick" Text="Get Quote" /> </Mobile:Form> <Mobile:Form runat="server" id="SecondForm"> <Mobile:Label runat="server" id="Code" /> <Mobile:Label runat="server" id="CompanyName" /> <Mobile:Label runat="server" id="Price" /> </Mobile:Form>

下载文档,方便阅读与编辑

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 5 金币 [ 分享文档获得金币 ]
1 人已下载

下载文档

相关文档