把Web Services生成服务器端C#、VB。或者接口

什么是Web Services?

  • Web Services 是应用程序组件
  • Web Services 使用开放协议进行通信
  • Web Services 是独立的(self-contained)并可自我描述
  • Web Services 可通过使用UDDI来发现
  • Web Services 可被其他应用程序使用
  • XML 是 Web Services 的基础

它如何工作?

  基础的 Web Services 平台是 XML + HTTP。

  HTTP 协议是最常用的因特网协议。

  XML 提供了一种可用于不同的平台和编程语言之间的语言。

Web services 平台的元素:

  • SOAP (简易对象访问协议)
  • UDDI (通用描述、发现及整合)
  • WSDL (Web services 描述语言)

 此文主要讲。通过Web Services 的WSDL生成C#代码

WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问。

首先来创建一个简单的服务,创建一个空Web应用程序,右键添加新建项,选择web服务,根据自己的需求命名

 

创建成功了。打开服务,生成了默认的文件代码

 

首先啥都不管,先运行看看,

DataInfo.asmx文件跟aspx文件一样,可以直接选中。右键在浏览器中查看

自此。你就看到了一个最简单的服务界面

 

 

这样你把这个服务发布到服务器。客户端就可以调用了。

现在手动调用试试,单击 "HelloWorld"

 

现在来尝试代码调用。把DataInfo.asmx服务发布到IIS。就好比别人发布了Web Services,现在我来调用

既然是测试。我就不用打开电脑的IIS了。用一卡西尼服务器即可。就是这个:CassiniDev4

这里提供一个下载地址:http://cassinidev.codeplex.com/

 

全路径就是这个:http://localhost:32768/DataInfo.asmx。在url地址栏打开就能看到

那么地址有了。在项目中就可以引用这个服务。

为了测试。这里在服务新增一个方法,返回两个数的和:Add(int x, int y)

/// <summary>
        
/// 返回两个数的和
        
/// </summary>
        
/// <param name="x"></param>
        
/// <param name="y"></param>
        
/// <returns></returns>
        [WebMethod(Description = "返回两数的和")]
        public int Add(int x, int y)
        {
            return x + y;
        }

 

方法名称上面添加WebMethod特性后。才能暴露在客户端,也就是说可以从远程Web客户端调用该方法

Description是对该方法的描述信息,会显示在客户端。添加完成,保存,F6重新生成代码。刷新浏览器你可以看到代码已经更新

好了。目前为止。服务已经配置好。并且已经发布。供别人免费使用。当有需要计算两个数之和的。就可以调用该服务

现在编写一个测试代码。创建一个项目。右键引用。选择添加服务引用

 

输入服务地址,命名。单击确定即可。当然你也可以看看该服务提供了那些方法。单击 "发现"

 

 

单击确定后。你发现。项目中已经生成了对该服务的引用

 

现在来编码调用里面的Add方法。创建一个页面。输入以下代码

protected void Page_Load(object sender, EventArgs e)
        {
            GetInfo.DataInfoSoapClient client = new GetInfo.DataInfoSoapClient();
            int result = client.Add(910);
            Response.Write(result);
        }

 

 

运行项目。成功的得到值为:19

那你有没有想过。当添加服务的引用后。内部都做了些什么。为什么添加以后就可以调用了呢?

把光标定位到Add方法。按F12转到方法的定义。

可以看到。其实已经生成了服务端的代码。

那这个代码在哪里呢。你根据项目的层次结构。

到项目的路径中看一看

 

打开Reference.cs 类。你会发现。里面生成了服务器代码。是自动生成是。别问我怎么知道的。它告诉我的:)

其实引用服务后,就生成服务的客户端代理类

 

哪天那个发布服务的人。一不小心。把Add方法的 "+" 改成了 "*",

  [WebMethod(Description = "返回两数的和")]
  public int Add(int x, int y)
  {
      return x * y;
  } 

客户端也会相应的更新,这就是一个同步更新

 

你也会发现。web.config里面有对服务的引用,

 <?xml version="1.0"?>

<configuration>

    <system.web>
        <compilation debug="true" targetFramework="4.0" />
    </system.web>

    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="DataInfoSoap" />
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:9213/DataInfo.asmx" binding="basicHttpBinding"
                bindingConfiguration
="DataInfoSoap" contract="GetInfo.DataInfoSoap"
                name
="DataInfoSoap" />
        </client>
    </system.serviceModel>
</configuration>

 

来分析下<system.serviceModel>.... </system.serviceModel>节点的含义

<!--此配置节包含所有 Windows Communication Foundation (WCF) ServiceModel 配置元素。-->
    <system.serviceModel>
      <!-- 此节包含标准绑定和自定义绑定的集合。 每一项均由其唯一的 name 进行标识。 服务通过用 name 与绑定进行链接来使用绑定。 -->
        <bindings>
            <!--绑定配置-->
            <basicHttpBinding>
                <!--每一项均由其唯一的 name 进行标识-->
                <binding name="DataInfoSoap" />
            </basicHttpBinding>
        </bindings>
      <!--此节包含客户端用来连接到服务的终结点的列表。-->
        <client>
          <!--终结点配置-->
            <endpoint address="http://localhost:9213/DataInfo.asmx" binding="basicHttpBinding"
                bindingConfiguration
="DataInfoSoap" contract="GetInfo.DataInfoSoap"
                name
="DataInfoSoap" />
        </client>
    </system.serviceModel>

 

详情:https://msdn.microsoft.com/zh-cn/library/ms731354

 

既然有人提供服务。也就会有人使用服务,

网上有很多对外公开的服务,比如:

获取天气的服务:http://www.webxml.com.cn/WebServices/WeatherWS.asmx

 

 

 

 

 

腾讯QQ查询状态http://webservice.webxml.com.cn/webservices/qqOnlineWebService.asmx

这些都是人家提供好了的。你只要直接在项目中引用。就像我上面的那样,在项目中引用其服务即可。因为这些是公共的。私有的另当别论。

但你有没有想过,如果你跟别人协同开发项目的时候。一个提供web服务,一个使用web服务。一个已经实现功能的WebService会发布自己的WSDL文件并不会发布到自己的服务器。那怎么办呢?

首先看看什么是WSDL?

WSDL(网络服务描述语言,Web Services Description Language)是一门基于 XML 的语言,用于描述 Web Services 以及如何对它们进行访问。

在服务后面加上wsdl

http://localhost:32768/DataInfo.asmx?wsdl。就可以得到当前服务的wsdl文件

然后把这个页面保存。保存为.wsdl文件即可,比如我保存在路径:

其实这样你依然可以在项目中添加该服务,地址为该路径即可

 

这样同样可以生成服务端C#代码,还有一种简单的方法。

使用VS2010提供的工具wsdl.exe由WSDL文件生成cs文件

 

 

看到界面:

 

 

 

输入wsdl回车,查看介绍

 

 

来分析下几个常用的命令:

默认为C#语言:

 

生成代码命令:

 

生成接口命令:

 

wsdl用法:

 

好了。现在来生成一个C#代码看看

 1:根据url路径生成代码,个人感觉没什么实际意义

来看看这条命令

wsdl是命令开始

/o:是开始输出

/o:后面是服务地址

生成的代码在

 

 

2:根据wsdl文件生成代码。如果上面的生成目录想根据自己来定义话。可以这样在 命令/o: 带上位置

 

从图片的标记可以看出来。已经成功了

来看看生成后的代码:

 //------------------------------------------------------------------------------

// <auto-generated>
//     此代码由工具生成。
//     运行时版本:4.0.30319.18444
//
//     对此文件的更改可能会导致不正确的行为,并且如果
//     重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;

// 
// 此源代码由 wsdl 自动生成, Version=4.0.30319.1。
// 


/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl""4.0.30319.1")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Web.Services.WebServiceBindingAttribute(Name="DataInfoSoap", Namespace="http://tempuri.org/")]
public partial class DataInfo : System.Web.Services.Protocols.SoapHttpClientProtocol {
    
    private System.Threading.SendOrPostCallback HelloWorldOperationCompleted;
    
    private System.Threading.SendOrPostCallback AddOperationCompleted;
    
    /// <remarks/>
    public DataInfo() {
        this.Url = "http://localhost:32768/DataInfo.asmx";
    }
    
    /// <remarks/>
    public event HelloWorldCompletedEventHandler HelloWorldCompleted;
    
    /// <remarks/>
    public event AddCompletedEventHandler AddCompleted;
    
    /// <remarks/>
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    public string HelloWorld() {
        object[] results = this.Invoke("HelloWorld"new object[0]);
        return ((string)(results[0]));
    }
    
    /// <remarks/>
    public System.IAsyncResult BeginHelloWorld(System.AsyncCallback callback, object asyncState) {
        return this.BeginInvoke("HelloWorld"new object[0], callback, asyncState);
    }
    
    /// <remarks/>
    public string EndHelloWorld(System.IAsyncResult asyncResult) {
        object[] results = this.EndInvoke(asyncResult);
        return ((string)(results[0]));
    }
    
    /// <remarks/>
    public void HelloWorldAsync() {
        this.HelloWorldAsync(null);
    }
    
    /// <remarks/>
    public void HelloWorldAsync(object userState) {
        if ((this.HelloWorldOperationCompleted == null)) {
            this.HelloWorldOperationCompleted = new System.Threading.SendOrPostCallback(this.OnHelloWorldOperationCompleted);
        }
        this.InvokeAsync("HelloWorld"new object[0], this.HelloWorldOperationCompleted, userState);
    }
    
    private void OnHelloWorldOperationCompleted(object arg) {
        if ((this.HelloWorldCompleted != null)) {
            System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
            this.HelloWorldCompleted(thisnew HelloWorldCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
        }
    }
    
    /// <remarks/>
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Add", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    public int Add(int x, int y) {
        object[] results = this.Invoke("Add"new object[] {
                    x,
                    y});
        return ((int)(results[0]));
    }
    
    /// <remarks/>
    public System.IAsyncResult BeginAdd(int x, int y, System.AsyncCallback callback, object asyncState) {
        return this.BeginInvoke("Add"new object[] {
                    x,
                    y}, callback, asyncState);
    }
    
    /// <remarks/>
    public int EndAdd(System.IAsyncResult asyncResult) {
        object[] results = this.EndInvoke(asyncResult);
        return ((int)(results[0]));
    }
    
    /// <remarks/>
    public void AddAsync(int x, int y) {
        this.AddAsync(x, y, null);
    }
    
    /// <remarks/>
    public void AddAsync(int x, int y, object userState) {
        if ((this.AddOperationCompleted == null)) {
            this.AddOperationCompleted = new System.Threading.SendOrPostCallback(this.OnAddOperationCompleted);
        }
        this.InvokeAsync("Add"new object[] {
                    x,
                    y}, this.AddOperationCompleted, userState);
    }
    
    private void OnAddOperationCompleted(object arg) {
        if ((this.AddCompleted != null)) {
            System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
            this.AddCompleted(thisnew AddCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
        }
    }
    
    /// <remarks/>
    public new void CancelAsync(object userState) {
        base.CancelAsync(userState);
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl""4.0.30319.1")]
public delegate void HelloWorldCompletedEventHandler(object sender, HelloWorldCompletedEventArgs e);

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl""4.0.30319.1")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class HelloWorldCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
    
    private object[] results;
    
    internal HelloWorldCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : 
            base(exception, cancelled, userState) {
        this.results = results;
    }
    
    /// <remarks/>
    public string Result {
        get {
            this.RaiseExceptionIfNecessary();
            return ((string)(this.results[0]));
        }
    }
}

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl""4.0.30319.1")]
public delegate void AddCompletedEventHandler(object sender, AddCompletedEventArgs e);

/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl""4.0.30319.1")]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
public partial class AddCompletedEventArgs : System.ComponentModel.AsyncCompletedEventArgs {
    
    private object[] results;
    
    internal AddCompletedEventArgs(object[] results, System.Exception exception, bool cancelled, object userState) : 
            base(exception, cancelled, userState) {
        this.results = results;
    }
    
    /// <remarks/>
    public int Result {
        get {
            this.RaiseExceptionIfNecessary();
            return ((int)(this.results[0]));
        }
    }
}

 

一眼是不是就看到了熟悉的代码?,对。

这个url就是服务的地址,更多的你可以自己去看代码,分析分析。

 

把这个类拖到你的项目中,测试

protected void Page_Load(object sender, EventArgs e)
        {
            /*
            GetInfo.DataInfoSoapClient client = new GetInfo.DataInfoSoapClient();
            int result = client.Add(9, 10);
            Response.Write(result);
             * 
*/

            DataInfo info = new DataInfo();
            int result = info.Add(95);
            Response.Write(result);
        }

 

如果想生成其他语言呢。比如vb ,从这里可以看出命令:

那就动手尝试下

 

 

还可以生成接口:通过/si命令

你会发现。保存的路径并不是D:\data,因为/si 命令没有这个选项,那怎么办呢?可以切换到D:\data目录

 

很显然。这次是我想要的结果了

 

 

看生成的代码是不是很简洁呢?

//------------------------------------------------------------------------------
// <auto-generated>
//     此代码由工具生成。
//     运行时版本:4.0.30319.18444
//
//     对此文件的更改可能会导致不正确的行为,并且如果
//     重新生成代码,这些更改将会丢失。
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Xml.Serialization;

// 
// 此源代码由 wsdl 自动生成, Version=4.0.30319.1。
// 


/// <remarks/>
[System.CodeDom.Compiler.GeneratedCodeAttribute("wsdl""4.0.30319.1")]
[System.Web.Services.WebServiceBindingAttribute(Name="DataInfoSoap", Namespace="http://tempuri.org/")]
public interface IDataInfoSoap {
    
    /// <remarks/>
    [System.Web.Services.WebMethodAttribute()]
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    string HelloWorld();
    
    /// <remarks/>
    [System.Web.Services.WebMethodAttribute()]
    [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Add", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
    int Add(int x, int y);
}

 

可以看到接口的名称是 IDataInfoSoap 。那么把这个接口拖到项目中。继承接口试试。

posted @ 2015-05-10 00:24  师太你就从了老衲吧  阅读(445)  评论(0编辑  收藏  举报