一、WebService中常用的属性(Attributes)
1. Web Service(Web服务)提供以下三个属性。
    Namespace:此属性的值包含 XML Web Service的默认命名空间。XML命名空间提供了一种在XML文档中创建名称的方法,该名称可由统一资源标识符(URI)标识。如果不指定命名空间,则使用默认命名空间 http://tempuri.org/
    Name:此属性的值包含XML Web Service的名称。在默认情况下,该值是实现XML Web Service的类的名称。
    Description:此属性的值包含描述性消息,此消息将在XML Web Service的说明文件(例如服务说明和服务帮助页)生成后显示给XML Web Service的潜在用户。
   
    示例代码如下:
    [WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Service : System.Web.Services.WebService
    {
        //......
    }
    运行结果:


    《图1》
   
2. WebMethod(Web服务方法)有以下4个常用属性。
   
    Description:是对Web Service方法的描述信息。就像Web Service方法的功能注释,可以让调用者看见的注释。
   
    示例代码如下:
    [WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Service : System.Web.Services.WebService
    {
        [WebMethod(Description = "显示所有人员的信息")]
        public InfoData[] GetInfos(out string emsg)
        {
            //...
        }
    }
    运行结果:


    《图2》
   
    EnableSession:指示Web Service是否启动Session标志,主要通过Cookie完成,默认为false。
    默认情况下WebService的方法中不能使用Session,如果使用会产生异常。
    示例代码如下:
    [WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Service : System.Web.Services.WebService
    {
        [WebMethod(Description = "显示所有人员的信息")]
        public InfoData[] GetInfos(out string emsg)
        {
            Session["test"] = DateTime.Now.ToString();
            return new InfoDA().Select().ToArray();
        }
    }
    运行结果:


    《图3》
   
    要在WebService中使用Session需要把上面的代码进行如下修改:
   
    [WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Service : System.Web.Services.WebService
    {
        [WebMethod(Description = "显示所有人员的信息", EnableSession = true)]
        public InfoData[] GetInfos(out string emsg)
        {
            Session["test"] = DateTime.Now.ToString();
            return new InfoDA().Select().ToArray();
        }
    }
   
    TransactionOption:指示Web Service方法的事务支持。
    要在WebService中使用事务时,不需要编写很多的代码,只需要在WebMethod属性中加上启用事务的声明即可
    示例代码如下:
    [WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Service : System.Web.Services.WebService
    {
        [WebMethod(TransactionOption= TransactionOption.RequiresNew)]
        public void AddInfo(InfoData data)
        {
            new InfoDA().Insert(data);
            new InfoDA().Insert(data);
        }
    }
    在上面的代码中向数据库中插入了两次数据,在第二次插入数据时会产生主键重复的异常。如果查看数据库时我们会发现第一次Insert也没有插入成功。这就是因为我们在该方法上加入了事务的功能。
   
    CacheDuration:设置响应应在缓存中保留的秒数。这样Web Service就不需要重复执行多遍,可以提高访问效率,而CacheDuration就是指定缓存时间的属性。
    示例代码如下:
    [WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class Service : System.Web.Services.WebService
    {
        [WebMethod( EnableSession=true, CacheDuration=10)]
        public string GetCNDateTime()
        {
            return DateTime.Now.ToString("yyyy年MM月dd日hh时mm分ss秒ms毫秒");
        }
    }
    上面的服务方法缓存了10秒钟。
    在我们运行该服务,手动调用方法的时候会发现好像缓存并没有起作用,每次调用的显示的时间总会变化。其实该缓存的效果在直接运行的时候并不会起作用,当我们编写客户端代码调用该服务的时候会发现缓存的确是起作用了。
    客户端代码如下:
    public static void Main(string[] args)
    {
        Services.MyServiceSoapClient client = new Client.Services.MyServiceSoapClient();
        string str = client.GetCNDateTime();
        Console.WriteLine(str);
    }
    在运行该客户端代码的时候,在10秒钟之内的两次运行显示的时间是不变的。
   
二、WebService的调用。
我们可以使用ASP.NET Web程序、WinForm程序、控制台程序和javascript来调用WebService。
ASP.NET、WinForm、控制台调用WebService方法基本一样也很简单,主要是添加Web引用,调用代理类来实现的,这里我们不再举例。
下面我们主要看一下如何使用JavaScript来调用WebService

WebService代码如下:
[WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
    [WebMethod]
    public string GetCNDateTime()
    {
        return DateTime.Now.ToString("yyyy年MM月dd日hh时mm分ss秒ms毫秒");
    }
}

客户端JS调用代码如下:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
    <div id="dd"></div>
    </div>
    </form>
</body>
</html>
<script language="javascript">
    function showTime() {
        //下面我们使用XMLDOM对象对WebService访问,因为WebService是以XML方式传输数据的,所以我们可以使用XMLDOM对象来解析WebService返回的数据
        var obj = new ActiveXObject("Microsoft.XMLDOM");
        //设定读取方式是同步方式
        obj.async = false;
        //指定XMLDOM对象要加载的WebService方法返回的XML数据
        //如果使用开发服务器的运行WebService的话,那需要选运行起这个WebService。
        obj.load("http://localhost/TestWS/Service.asmx/GetCNDateTime");
        //取得返回的XML数据中的文本
        var res = obj.documentElement.text;
        dd.innerHTML = res;
    }
    window.setInterval(showTime, 1000);
</script>

这样运行并不成功会产生下面的问题:


《图4》

这是因为WebService并不接收JavaScript提交的方式。要完善这个问题我们需要在WebService的web.config配置文件中加入下面的配置
<system.web>
        <webServices>
            <protocols>
                <add name="HttpPost"/>
                <add name="HttpGet"/>
            </protocols>
        </webServices>
        .........
</system.web>


《图5》

三、实现异步调用Web Service

通调用Web Service的方法,在Web
Service执行期间客户端会一直等待服务执行完毕才能响应。从而造成客户端UI线程的阻塞假死现象。这时候,异步调用就显得很有用,它可以让客户端在
调用Web Service时,不至于阻塞客户端的UI线程导致假死,还可以在调用Web Service的同时做些其他的处理。
第一种方法,是通过利用Backgroundworker对象实现。
BackgroundWorker

类允许你在单独的专用线程上运行操作。耗时的操作(如下载和数据库事务)在长时间运行时可能会导致用户界面(UI)似乎处于停止响应状态。如果你需要能进
行响应的用户界面,而且面临与这类操作相关的长时间延迟,则可以使用 BackgroundWorker 类方便地解决问题。
class Program
{
    public static void Main(string[] args)
    {
        //实现异步调用
        BackgroundWorker bgw = new BackgroundWorker();
        //DoWork事件是在BackgroundWorker对象调用RunWorkerAsync()方法后要触发的事件
        bgw.DoWork += new DoWorkEventHandler(bgw_DoWork);  
        //RunWorkerCompleted事件是DoWork指向的方法执行完成的回调事件
        bgw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
        //启运异步调用
        bgw.RunWorkerAsync();
        Debug.WriteLine("Main Function is Over....");
        Console.ReadLine();
    }

static void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Debug.WriteLine("Work is over...");
    }

static void bgw_DoWork(object sender, DoWorkEventArgs e)
    {
        Debug.WriteLine("Work is Processing...");
    }
}

打印的结果应当是:
Main Function is Over....
Work is Processing...
Work is over...

其中的Main函数线程和bgw_DoWork线程同时运行的。

第二种方法,是调用Web Service的WebMethod中的Async方法实现。
当添加完Web Service的引用以后,会在本地生成代理类,其中,会有一个和原Web Service方法名字相同而后缀是Async的方法。
在.NET FrameWork3.5中并不会自动产生这种异步方法。需要我们来生成一下。
在“Web引用”上右击,选择“配置服务引用...”


《图6》
在服务引用设置窗口中把“生成异步操作”复选框选中点击确定。


《图7》
在客户端编写代码的时候,我们会看到代理类中的每个方法都多了个异步操作的方法


《图8》
客户端完整代码如下:
public static void Main(string[] args)
{
    Services.MyServiceSoapClient client = new Client.Services.MyServiceSoapClient();
   
client.GetCNDateTimeCompleted += new
EventHandler<Client.Services.GetCNDateTimeCompletedEventArgs>(client_GetCNDateTimeCompleted);
    client.GetCNDateTimeAsync();
    Debug.WriteLine("Doing other things");
    Console.ReadLine();
}
运行结果如图所示:


《图9》

四、保证Web Service的安全
要以安全的方式访问Web服务方法,可以考虑以下安全措施:
    是谁调用?——SoapHeader身份认证。
    来自哪里?——访问IP认证。
    加密传输 ——SSL安全访问。
在这里我们主要来讨论前两种措施,至于SSL安全访问需要对操作系统进行配置,这里不再赘述。
(一)SoapHeader身份认证。
1.在Web Service中定义自己的SoapHeader派生类。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services.Protocols;

public class MySoapHeader:SoapHeader
{
    private string _UserName;

public string UserName
    {
        get { return _UserName; }
        set { _UserName = value; }
    }
    private string _Password;

public string Password
    {
        get { return _Password; }
        set { _Password = value; }
    }
    public MySoapHeader() { }
    public MySoapHeader(string uid,string pwd)
    {
        _UserName = uid;
        _Password = pwd;
    }
    public bool IsValid(out string errorMsg)
    {
        errorMsg = "";
        if (_UserName == "admin" && _Password == "123")
        {
            return true;
        }
        else
        {
            errorMsg = "您无权调用该服务";
            return false;
        }
    }
}

2.在Web Service中添加基于SoapHeader验证的Web Service接口方法:
[WebService(Description="测试WebService属性", Name="MyService", Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class Service : System.Web.Services.WebService
{
    public MySoapHeader SoapHeader = new MySoapHeader();
   [SoapHeader("SoapHeader")]
    [WebMethod(Description = "显示所有人员的信息")]
    public InfoData[] GetInfos(out string emsg)
    {
        if (!SoapHeader.IsValid(out emsg))
            return null;
        return new InfoDA().Select().ToArray();
    }
}

3.在客户端调用具有SoapHeader的Web Service
Services.MyServiceSoapClient client = new Client.Services.MyServiceSoapClient();
Services.MySoapHeader header = new Client.Services.MySoapHeader();
header.UserName = "admin";
header.Password = "asasas";

e.Result = client.GetInfos(header,out outmsg);
Console.WriteLine(outmsg);

《图10》

(二)访问IP认证。
对来源IP的检查来进行验证,我们只允许指定IP的服务器来访问,保证点对点的安全。
bool ValidateIP(int UserID, out string exceptionInfo)
{
    exceptionInfo = "";
    string uip = HttpContext.Current.Request.UserHostAddress;
    Common dal = new Common();
    List<string> ips = dal.GetPermitIp(UserID);//得到该用户ID所允许的IP列表
    if (ips == null || ips.Count == 0)
    {
        exceptionInfo = "调用Web服务的客户端IP未被允许,无法访问!";
        return false;
    }
    if (ips.Contains(uip)) //允许IP列表中包含该IP
    {
        return true;
    }
    exceptionInfo = "调用Web服务的客户端IP未被允许,无法访问!";
    return false;
}
在具体Web方法里调用该方法检查用户访问者是否是以我们允许的IP进行访问的,以确保安全。
    优点:简单,防止非指定客户机器访问。
    缺点:IP是可以伪造的;维护IP地址表比较烦琐。且只适合于固定IP访问者的情况。

Web Service开发中需要注意的问题
WebMethod的名字、参数和返回值应该一看就知道这接口大概是干什么用的。
WebMethod参数要尽量简单。只有一个参数的服务接口,往往不能满足业务需求。但过多的参数也提高了出错的几率
WebMethod要提供对参数和返回值的校验
WebMethod返回值应该是简单的语言无关
WebMethod谨慎地抛出异常
    对Web Service中的任何异常都应该进行相应的处理。可以简单地归纳为以下两种情况。
        第1种情况是返回值是简单类型,比如bool型,就true和false两种情况,不抛出异常怎么办?选择有两种,一是抛出异常,二是改变接口,返回int用1和0对应true和false,用-1对应系统异常。
        第2种情况是返回值是复杂对象,可以通过参数out string exceptionInfo来返回异常信息。

WebMethod禁用HTTP POST/GET协议
    Web服务绑定到3种协议:HTTP/POST、HTTP/GET和SOAP。HTTP/GET的安全性不如SOAP。
WebMethod避免使用ASP.NET会话状态

WebService开发常用功能详解的更多相关文章

  1. Fiddler抓取https请求 & Fiddler抓包工具常用功能详解

    Fiddler抓取https请求 & Fiddler抓包工具常用功能详解   先来看一个小故事: 小T在测试APP时,打开某个页面展示异常,于是就跑到客户端开发小A那里说:“你这个页面做的有问 ...

  2. Jmeter常用功能详解

    嘻嘻,忙碌的一周,马上就到周四了~明天就是周五了,可以去嗨了! 这几天正式成立了一个微信订阅号,旨在免费帮助需要入门软件测试的小白! 各位走过路过的亲,欢迎订阅哦:扫描二维码即可订阅

  3. fiddler抓包常用功能详解

    一.基础部分: 1.设置代理ip及端口,tools --> telerik fiddler options --> connections -->勾选 “ Allow romote ...

  4. (数据科学学习手札21)sklearn.datasets常用功能详解

    作为Python中经典的机器学习模块,sklearn围绕着机器学习提供了很多可直接调用的机器学习算法以及很多经典的数据集,本文就对sklearn中专门用来得到已有或自定义数据集的datasets模块进 ...

  5. JMeter5.1企业级应用应用常用功能详解(含插件安装)

    apache jmeter是100%的java桌面应用程序,它被设计用来加载被测试软件功能特性.度量被测试软件的性能.jmeter可以模拟大量的服务器负载,并且jmeter提供图形化的性能分析. JM ...

  6. Vim 命令常用功能详解

    Vim编辑器 文本编辑器 , 字处理器ASCIIvi:Visual Interface vim :VI iMproved 全屏编辑器,模式化编辑器vim 模式:编辑模式(命令模式)输入模式末行模式 模 ...

  7. chattr的常用参数详解

    chattr的常用参数详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 在实际生产环境中,有的运维工程师不得不和开发和测试打交道,在我们公司最常见的就是部署接口.每天每个人部署的 ...

  8. 【转】【Android UI设计与开发】之详解ActionBar的使用,androidactionbar

    原文网址:http://www.bkjia.com/Androidjc/895966.html [Android UI设计与开发]之详解ActionBar的使用,androidactionbar 详解 ...

  9. .NET ORM框架 SqlSuagr4.0 功能详解与实践【开源】

    SqlSugar 4.0 ORM框架的优势 为了未来能够更好的支持多库分布式的存储,并行计算等功能,将SqlSugar3.x全部重写,现有的架构可以轻松扩展多库. 源码下载: https://gith ...

随机推荐

  1. Google Android官方文档进程与线程(Processes and Threads)翻译

    android的多线程在开发中已经有使用过了,想再系统地学习一下,找到了android的官方文档,介绍进程与线程的介绍,试着翻译一下. 原文地址:http://developer.android.co ...

  2. [OC Foundation框架 - 9] NSMutableArray

    可变的NSArray,可以随意添加OC对象   1.创建 void arrayCreate() { NSMutableArray *array = [NSMutableArray arrayWithO ...

  3. ASP.NET基础系列

    一.HttpContext概述 1).如何获取对象: 在WebForm或类库(包括MVC)项目中,通过Current静态属性,就能够获得HttpContext的对象: HttpContext cont ...

  4. XML操作之Linq to Xml

    需要引用的命名空间:   using System.Xml.Linq; 常用的类:XDocument.XElement.XAttribute 创建 XDocument对象. XDocument.Loa ...

  5. Oracle 监听器无法启动(TNS-12537,TNS-12560,TNS-00507)

    Oracle启动监听报错,提示 连接中断 [oracle@localhost ~]$ lsnrctl start LSNRCTL for Linux: Version 11.2.0.1.0 - Pro ...

  6. IOS开发之 ---- 苹果系统代码汉字转拼音

    NSString *hanziText = @"我是中国人";   if ([hanziText length]) {       NSMutableString *ms = [[ ...

  7. Android事件分发原理

    终于用上了word 2013来写博客,感觉真是老好了,以前在网页上写,老是要把网页拖上拖下的,每次都要吐一升老血啊,现在用上本地的word,瞬间感觉好多了.还有感谢为word写插件的这个大神,代码高亮 ...

  8. 别名的应用(New-Alias)

    New-Alias -name appcmd -value $env:windir\system32\inetsrv\appcmd.exe 这样就可以在当前PS环境下直接使用appcmd了

  9. paip.提升性能---- 网站并发数的总结.txt

    paip.提升性能---- 网站并发数的总结.txt 作者Attilax ,  EMAIL:1466519819@qq.com  来源:attilax的专栏 地址:http://blog.csdn.n ...

  10. [MODx] 6. Cache '!' with login package

    1. Install login package. 2. Create a Template called 'login': [[!Login? &loginResourceId=`13` / ...