一、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会话状态

转载于:https://www.cnblogs.com/mooncher/p/3484202.html

WebService开发常用功能详解相关推荐

  1. 3dmax基础知识:3dmax常用功能详解,零基础小白的福音

    你收藏了那么多教程,却不知道3dmax怎么入门?掌握3dmax常用功能是3dmax入门的基础之一,今天就为您盘点了一些3dmax最常用到的功能和使用方法,快来和小编一起学习3dmax入门基础知识吧! ...

  2. Google Earth常用功能详解

    文件 导入是最重要的功能,可以导入路径.图像.模型. 编辑 复制,如果选中路径对象将会复制为KML的XML语言文本. 复制为航迹,可以复制路径,但不清楚用途. 复制图像就是将当前窗口截屏. 复制视图位 ...

  3. 3D游戏建模入门基础:3dmax常用功能详解

    你收藏了那么多教程,却不知道3dmax怎么入门?掌握3dmax常用功能是3dmax入门的基础之一,所以呢小编今天就为您盘点了一些3dmax最常用到的功能和使用方法,快来和小编一起学习3dmax入门基础 ...

  4. cakephp index.php,CakePHP开发常用技巧详解

    问:开发中,程序一般设定debug为2,如何在某一个特定的action中关闭debug?答:Configure::write('debug', 0); 问:如何静态化某个action渲染的视图? 答: ...

  5. Fiddler抓包工具入门及常用功能详解

    先来看一个小故事: 小T在测试APP时,打开某个页面展示异常,于是就跑到客户端开发小A那里说:"你这个页面做的有问题,页面展示异常": 小A说:"这哪是我的问题,你去找后 ...

  6. android 电话 快捷键,Android studio开发常用快捷键详解

    最常用快捷键 1.Ctrl+E可以显示最近编辑的文件列表 2.Shift+Click(点击)可以关闭文件 3.Ctrl+[或者ctrl+]可以跳到大括号的开头结尾 4.Ctrl+Shift+Backs ...

  7. 太极计算机ehr系统,(数据科学学习手札21)sklearn.datasets常用功能详解

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

  8. css 渐变 椭圆,CSS3圆角和渐变2种常用功能详解

    Css3圆角讲解:想必大家对于图片,背景圆角,都不陌生吧, 圆角语法:border-radius:圆角值: CSS3圆角的优点 传统的圆角生成方案,必须使用多张图片作为背景图案.CSS3的出现,使得我 ...

  9. Vim 命令常用功能详解

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

最新文章

  1. 伦敦大学学院开源物体级语义SLAM!支持单/双目+LiDAR!
  2. 14.相同的树另一棵树的子树检查子树二叉树中的列表(教你们使用相同的套路快速解决这四道题)
  3. IO 模拟 1/2 Bias、1/4 Duty的 LCD 驱动
  4. eset14 杀毒清除无提示
  5. [Java基础]Lambda表达式的省略模式
  6. KeeperErrorCode = Unimplemented for /test
  7. sr650服务器cpu型号,至强Gold 联想ThinkSystem SR650评测
  8. QML工作笔记-文本输入设置长度以及回显方式(TextInput与TextField通用)
  9. http://jingyan.baidu.com/article/2009576193ee38cb0721b416.html
  10. iOS开发,轻松获取根控制器当前控制器的正确方式
  11. 打印显示服务器存储空间不足,服务器存储空间不足,无法处理此命令。 ID 2019 或 2020...
  12. 阿里云ace考试有什么用?想要通过需要掌握哪些方面知识?
  13. 没有自制力的人有什么资格谈努力
  14. ICCV 2019|70 篇论文抢先读,含目标检测/自动驾驶/GCN/等(提供PDF下载)
  15. 大量数据导出Excel 之 多重影分身之术
  16. 打印论文是单面还是双面?
  17. hdu 6578 Blank dp求 给定区间中数字不同的方案数
  18. 华为双前置摄像头_华为nova7 Pro的前置是两个摄像头吗?自拍功能咋样
  19. 在Ubuntu中获取奥比中光的深度值 Python代码
  20. 教资照片可以用计算机么,2015教资国考|图像、声音、视频的加工【专项练习二】...

热门文章

  1. html的各种基本标签 fylong,HTML:text标签不工作
  2. easymock参数_EasyMock捕获参数
  3. Hibernate Session get()vs load()实例差异
  4. python列重命名_Python目录–创建,重命名,删除,列出,更改
  5. msbuild.exe编译c#项目
  6. 开课吧:OOM常见的解决方案有哪些?
  7. Java基础篇之Java线程模型
  8. 嵌入式学习步骤及方法(精典)
  9. 在网页在播放flv格式的视频
  10. linux下如何关闭防火墙、查看当前的状态、开放端口