测试代码链接
Web Services 简介:
Web Services 可使您的应用程序成为 Web 应用程序。
Web Services 通过 Web 进行发布、查找和使用。
Web Service是一个平台独立的,低耦合的,自包含的、基于可编程的web的应用程序,可使用开放的XML(标准通用标记语言下的一个子集)标准来描述、发布、发现、协调和配置这些应用程序,用于开发分布式的交互操作的应用程序。
Web Service技术,能使得运行在不同机器上的不同应用无须借助附加的、专门的第三方软件或硬件,就可相互交换数据或集成。
依据Web Service规范实施的应用之间,无论它们所使用的语言、平台或内部协议是什么,都可以相互交换数据。
Web Service是自描述、自包含的可用网络模块,可以执行具体的业务功能。
Web Service也很容易部署,因为它们基于一些常规的产业标准以及已有的一些技术,诸如标准通用标记语言下的子集XML、HTTP。
Web Service减少了应用接口的花费。Web Service为整个企业甚至多个组织之间的业务流程的集成提供了一个通用机制。
什么是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 平台的元素:
Web Services 拥有三种基本的元素:SOAP、WSDL 以及 UDDI。
SOAP (简易对象访问协议)
UDDI (通用描述、发现及整合)
WSDL (Web services 描述语言)
什么是 SOAP?
基本的 Web services 平台是 XML + HTTP。
SOAP 指简易对象访问协议
SOAP 是一种通信协议
SOAP 用于应用程序之间的通信
SOAP 是一种用于发送消息的格式
SOAP 被设计用来通过因特网进行通信
SOAP 独立于平台
SOAP 独立于语言
SOAP 基于 XML
SOAP 很简单并可扩展
SOAP 允许您绕过防火墙
SOAP 将作为 W3C 标准来发展
什么是 WSDL?
WSDL 是基于 XML 的用于描述 Web Services 以及如何访问 Web Services 的语言。
WSDL 指网络服务描述语言
WSDL 使用 XML 编写
WSDL 是一种 XML 文档
WSDL 用于描述网络服务
WSDL 也可用于定位网络服务
WSDL 还不是 W3C 标准
什么是UDDI?
UDDI 是一种目录服务,通过它,企业可注册并搜索 Web services。
UDDI 指通用的描述、发现以及整合(Universal Description, Discovery and Integration)。
UDDI 是一种用于存储有关 web services 的信息的目录。
UDDI 是一种由 WSDL 描述的网络服务接口目录。
UDDI 经由 SOAP 进行通迅。
UDDI 被构建于 Microsoft .NET 平台之中。
为什么要使用WebService:
最重要的事情是协同工作。
由于所有主要的平台均可通过 Web 浏览器来访问 Web,不同的平台可以借此进行交互。为了让这些平台协同工作,Web 应用程序被开发了出来。
Web 应用程序是运行在 Web 上的简易应用程序。它们围绕 Web 浏览器标准被进行构建,几乎可被任何平台之上的任何浏览器来使用。
1.跨平台调用(WebService不局限于操作系统,你可以在Windows上调用linux上的WebService服务,反之亦然,其他系统同理);
2.跨语言调用(WebService不局限于编程语言,你可以在Java语言中调用C#语言提供的WebService服务,反之亦然,其他语言同理);
3.可远程调用(通过使用WebService,您的应用程序可以向全世界发布信息,或提供某项功能,只要有Internet)。
Web services 把 Web 应用程序提升到了另外一个层面
通过使用 Web services,您的应用程序可向全世界发布功能或消息。
Web services 使用 XML 来编解码数据,并使用 SOAP 借由开放的协议来传输数据。
通过 Web services,您的会计部门的 Win 2k 服务器可与 IT 供应商的 UNIX 服务器进行连接。
Web services 有两种类型的应用
可重复使用的应用程序组件
有一些功能是不同的应用程序常常会用到的。那么为什么要周而复始地开发它们呢?
Web services 可以把应用程序组件作为服务来提供,比如汇率转换、天气预报或者甚至是语言翻译等等。
比较理想的情况是,每种应用程序组件只有一个最优秀的版本,这样任何人都可以在其应用程序中使用它。
连接现有的软件
通过为不同的应用程序提供一种链接其数据的途径,Web services有助于解决协同工作的问题。
通过使用 Web services,您可以在不同的应用程序与平台之间来交换数据。
其他
WebService:托管于IIC web形式 http/https
WebService5个层次:
1 Http协议:基于Http完成的请求/响应,数据是以header/body去request,以header/body来response 通过code确定响应
2 XML格式:跨平台
3 SOAP协议:header/body 放入的是XML数据,SOAP协议是用来把一个操作翻译成XML,也可以把XML还原成操作
4 WSDL:webservice的描述语言
5 UDDI:找服务的机制
http是传输协议,soap是解析协议
WebSerive不能泛型
对外是webapi 对内WCF
WebService都可以,都没那么犀利
js是可以直接调用WebService
WebService安全问题:
1 内部使用,不存在
2 Form windows身份,通过配置
3 服务方法加个参数,token 定时更新+沟通
4 SoapHeader
下面以MVC调用webservice服务简单举例
编写webservice服务
在空网站WebService1Host中添加Web服务WebService1.asmx,有两个服务方法。(Web服务WebService1.asmx寄宿于网站WebService1Host)
打开电脑的Internet Information Service (IIC)管理器添加网站WebService1Host,部署为本地IIC。
点击浏览服务寄宿网站报出如下错误
需要启动目录浏览功能和设置默认文档
成功浏览服务寄宿网站
在MVC中使用webservice服务
添加服务引用点击发现能自动查找IIC Experss上的服务地址
这里我们使用的是在前面部署到本地的IIC
MVC+WebService+easyui实现CRUD案例
存放到集合的对象
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace WebApiCommon
{
public class Contact
{
public string Id { get; set; }
public string Name { get; set; }
public string PhoneNo { get; set; }
public string EmailAddress { get; set; }
public string Address { get; set; }
}
}
WebService服务端:寄宿于WebService1Host的WebService。提供对集合增删查改WebService接口
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using WebApiCommon;
namespace WebService1Host
{
///
/// WebService1 的摘要说明
///
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消注释以下行。
// [System.Web.Script.Services.ScriptService]
public class WebService1 : System.Web.Services.WebService
{
public CustomSoapHeader CustomSoapHeader;
static List<Contact> contacts;
static int counter = 2;
static WebService1()
{
contacts = new List<Contact>();
contacts.Add(new Contact { Id = "001", Name = "张三", PhoneNo = "0512-12345678", EmailAddress = "[email protected]", Address = "江苏省苏州市星湖街328号" });
contacts.Add(new Contact { Id = "002", Name = "李四", PhoneNo = "0512-23456789", EmailAddress = "[email protected]", Address = "江苏省苏州市金鸡湖大道328号" });
}
[WebMethod]//服务方法对外公开标识
public string HelloWorld()
{
return "Hello World";
}
[WebMethod]
public int Add(int a,int b)
{
return a + b;
}
[WebMethod]
public List<Contact> Select(string id = null)//无法序列化接口 System.Collections.Generic.IEnumerable
{
return (from contact in contacts
where contact.Id == id || string.IsNullOrEmpty(id)
select contact).ToList();
}
[WebMethod]
public void Insert(Contact contact)
{
Interlocked.Increment(ref counter);
contact.Id = counter.ToString("D3");
contacts.Add(contact);
}
[WebMethod]
public void Update(Contact contact)
{
contacts.Remove(contacts.First(c => c.Id == contact.Id));
contacts.Add(contact);
}
[WebMethod]
public void Delete(string id)
{
contacts.Remove(contacts.First(c => c.Id == id));
}
[WebMethod]
[System.Web.Services.Protocols.SoapHeader("CustomSoapHeader")]
public string CustomSoapHeaderTest()
{
if (this.CustomSoapHeader != null && this.CustomSoapHeader.Validate())
{
return "身份验证通过";
}
else
{
throw new SoapException("身份验证不通过", SoapHeaderException.ServerFaultCode);
}
}
}
}
客户端:MVC控制器对集合增删查改代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using WebApiCommon;
namespace WebApiLearnApp.Controllers
{
public class WebServiceCRUDController : Controller
{
// GET: WebServiceCRUD
public ActionResult Index()
{
return View();
}
public ActionResult Select()
{
using (ServiceReference1.WebService1SoapClient client = new ServiceReference1.WebService1SoapClient())
{
var a = client.Select(null);
return Json(a, JsonRequestBehavior.AllowGet);//从webservice中获取json数据
}
}
public ActionResult Insert(Contact contact)
{
WebApiLearnApp.ServiceReference1.Contact contact1 = new ServiceReference1.Contact()
{
Name = contact.Name,
PhoneNo = contact.PhoneNo,
EmailAddress = contact.EmailAddress,
Address = contact.Address
} ;
using (ServiceReference1.WebService1SoapClient client = new ServiceReference1.WebService1SoapClient())
{
client.Insert(contact1);
}
return Content("ok");
}
public ActionResult Delete()
{
string strId = Request["strId"];
using (ServiceReference1.WebService1SoapClient client = new ServiceReference1.WebService1SoapClient())
{
client.Delete(strId);
}
return Content("ok");
}
public ActionResult ShowEdit()
{
string id = Request["rowsid"];
using (ServiceReference1.WebService1SoapClient client = new ServiceReference1.WebService1SoapClient())
{
var a = client.Select(id);
return Json(a, JsonRequestBehavior.AllowGet);
}
}
public ActionResult Edit(Contact contact)
{
WebApiLearnApp.ServiceReference1.Contact contact1 = new ServiceReference1.Contact()
{
Name = contact.Name,
PhoneNo = contact.PhoneNo,
EmailAddress = contact.EmailAddress,
Address = contact.Address
};
using (ServiceReference1.WebService1SoapClient client = new ServiceReference1.WebService1SoapClient())
{
client.Update(contact1);
}
return Content("ok");
}
}
}
MVC客户端easyui 界面视图代码
@{
Layout = null;
}
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<link href="~/Content/themes/default/easyui.css" rel="stylesheet" />
<link href="~/Content/themes/icon.css" rel="stylesheet" />
<script src="~/Scripts/jquery-1.7.1.min.js"></script>
<script src="~/Scripts/jquery.easyui.min.js"></script>
<script src="~/Scripts/easyui-lang-zh_CN.js"></script>
<script src="~/Scripts/datapattern.js"></script>
<script src="~/Scripts/jquery.unobtrusive-ajax.min.js"></script>
<script src="~/Scripts/jquery.validate.min.js"></script>
<script type="text/javascript">
$(function () {
$("#addDiv").css("display", "none");
$("#editDiv").css("display", "none");
loadData();
});
function loadData(pars) {
$('#tt').datagrid({
url: '/WebServiceCRUD/Select',
title: '用户数据表格',
width: 700,
height: 400,
fitColumns: true, //列自适应
nowrap: false,
idField: 'Id',//主键列的列明
loadMsg: '正在加载用户的信息...',
pagination: false,//是否有分页
singleSelect: false,//是否单行选择
pageSize: 10,//页大小,一页多少条数据
pageNumber: 1,//当前页,默认的
pageList: [5, 10, 15],
queryParams: pars,//往后台传递参数
columns: [[//c.UserName, c.UserPass, c.Email, c.RegTime
{ field: 'ck', checkbox: true, align: 'left', width: 50 },
{ field: 'Id', title: '编号', width: 60 },
{ field: 'Name', title: '姓名', width: 80 },
{ field: 'PhoneNo', title: '电话', width: 80 },
{ field: 'EmailAddress', title: '邮箱', width: 120 },
{ field: 'Address', title: '地址', width: 120 }
]],
toolbar: [{
id: 'btnDelete',
text: '删除',
iconCls: 'icon-remove',
handler: function () {
deleteInfo();
}
}, {
id: 'btnAdd',
text: '添加',
iconCls: 'icon-add',
handler: function () {
addInfo();
}
}, {
id: 'btnEidt',
text: '编辑',
iconCls: 'icon-edit',
handler: function () {
showEditInfo();
}
}],
});
}
//删除数据
function deleteInfo() {
var rows = $('#tt').datagrid('getSelections');//获取所选择的行
if (!rows || rows.length == 0) {
//alert("请选择要修改的商品!");
$.messager.alert("提醒", "请选择要删除的记录!", "error");
return;
}
$.messager.confirm("提示", "确定要删除数据吗", function (r) {
if (r) {
//获取要删除的记录的ID值。
var rowsLength = rows.length;
var strId = "";
for (var i = 0; i < rowsLength; i++) {
strId = strId + rows[i].Id + ",";//1,2,3,
}
//去掉最后一个逗号.
strId = strId.substr(0, strId.length - 1);
//将获取的要删除的记录的ID值发送到服务端.
$.post("/WebServiceCRUD/Delete", { "strId": strId }, function (data) {
if (data == "ok") {
$('#tt').datagrid('reload');//加载表格不会跳到第一页。
//清除上次操作的历史的记录。
$('#tt').datagrid('clearSelections')
} else {
$.messager.alert("提醒", "删除记录失败!", "error");
}
});
}
});
}
//添加数据
function addInfo() {
$("#addDiv").css("display", "block");
$('#addDiv').dialog({
title: '添加用户数据',
width: 300,
height: 200,
collapsible: true,
maximizable: true,
resizable: true,
modal: true,
buttons: [{
text: 'Ok',
iconCls: 'icon-ok',
handler: function () {
$("#addForm").submit();//提交表单
}
}, {
text: 'Cancel',
handler: function () {
$('#addDiv').dialog('close');
}
}]
});
}
//完成添加后调用该方法
function afterAdd(data) {
if (data == "ok") {
$('#addDiv').dialog('close');
$('#tt').datagrid('reload');//加载表格不会跳到第一页。
$("#addForm input").val("");//清空表单input标签数据
}
}
//展示一下要修改的数据.
function showEditInfo() {
//判断一下用户是否选择了要修改的数据
var rows = $('#tt').datagrid('getSelections');//获取所选择的行,也只能一行
if (rows.length != 1) {
$.messager.alert("提示", "请选择要修改的数据", "error");
return;
}
//将要修改的数据查询出来,显示到文本框中。
var rowsid = rows[0].Id;//从选中的行拿id
//$.post异步请求
$.post("/WebServiceCRUD/ShowEdit", { "rowsid": rowsid }, function (data) {
$("#txtId").val(data.Id);
$("#txtName").val(data.Name);
$("#txtPhoneNo").val(data.PhoneNo);
$("#txtEmailAddress").val(data.EmailAddress);
$("#txtAddress").val(data.Address);
});
$("#editDiv").css("display", "block");
$('#editDiv').dialog({
title: '编辑用户数据',
width: 300,
height: 200,
collapsible: true,
maximizable: true,
resizable: true,
modal: true,
buttons: [{
text: 'Ok',
iconCls: 'icon-ok',
handler: function () {
$("#editForm").submit();//提交表单
}
}, {
text: 'Cancel',
handler: function () {
$('#editDiv').dialog('close');
}
}]
});
}
//更新以后调用该方法.
function afterEdit(data) {
if (data == "ok") {
$('#editDiv').dialog('close');
$('#tt').datagrid('reload');//加载表格不会跳到第一页。
} else {
$.messager.alert("提示", "修改的数据失败", "error");
}
}
</script>
</head>
<body>
<div>
<table id="tt" style="width: 700px;" title="标题,可以使用代码进行初始化,也可以使用这种属性的方式" iconcls="icon-edit">
</table>
</div>
<!--------------添加数据---------------------->
<div id="addDiv">
@using (Ajax.BeginForm("Insert", "WebServiceCRUD", new { }, new AjaxOptions() { HttpMethod = "post", OnSuccess = "afterAdd" }, new { id = "addForm" }))
{
<table>
<tr><td>姓名</td><td><input type="text" name="Name" /></td></tr>
<tr><td>电话</td><td><input type="password" name="PhoneNo" /></td></tr>
<tr><td>邮箱</td><td><input type="text" name="EmailAddress" /></td></tr>
<tr><td>地址</td><td><input type="text" name="Address" /></td></tr>
</table>
}
</div>
<!--------------修改数据---------------------->
<div id="editDiv">
@using (Ajax.BeginForm("Edit", "WebServiceCRUD", new { }, new AjaxOptions() { HttpMethod = "post", OnSuccess = "afterEdit" }, new { id = "editForm" }))
{
<input type="hidden" name="Id" id="txtId" />
<table>
<tr><td>姓名</td><td><input type="text" name="Name" id="txtName" /></td></tr>
<tr><td>电话</td><td><input type="text" name="PhoneNo" id="txtPhoneNo" /></td></tr>
<tr><td>邮箱</td><td><input type="text" name="EmailAddress" id="txtEmailAddress" /></td></tr>
<tr><td>地址</td><td><input type="text" name="Address" id="txtAddress" /></td></tr>
</table>
}
</div>
</body>
</html>
添加
删除
更新有bug。。。。 从服务器返回到视图的json id有值,但是提交表单的对象id属性为null。。。。
使用SoapHeader对WebService进行安全问题
在webservice服务端添加验证对象CustomSoapHeader
和验证方法public bool Validate()
需要继承System.Web.Services.Protocols.SoapHeader
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace WebService1Host
{
///
/// Header:分配个加密钥 账号密码加密
///
///
public class CustomSoapHeader : System.Web.Services.Protocols.SoapHeader
{
private string userName = string.Empty;
private string passWord = string.Empty;
public CustomSoapHeader()//必须有一个无参数的构造函数
{ }
///
/// 构造函数
///
/// 用户名
/// 密码
public CustomSoapHeader(string userName, string passWord)
{
this.userName = userName;
this.passWord = passWord;
}
///
/// 获取或设置用户用户名
///
public string UserName
{
get { return userName; }
set { this.userName = value; }
}
///
/// 获取或设置用户密码
///
public string PassWord
{
get { return passWord; }
set { this.passWord = value; }
}
public bool Validate()
{
return this.UserName.Contains("s") && this.PassWord.Contains("1");
}
}
}
在webservice中添加验证信息
mvc控制器中使用带SoapHeader验证的webservice服务接口
测试如图
调用远程的WebService
WebXml.com.cn 天气预报 Web 服务 http://ws.webxml.com.cn/WebServices/WeatherWebService.asmx
直接添加服务引用成功了,但是运行报错:System.ServiceModel.FaultException:“服务器无法处理请求。 —> 未将对象引用设置到对象的实例。”
解决办法:
这是ASP.NET的问题,Microsoft原想用服务引用完全兼容web引用,但是有时候会出现问题。
你调用的是一个WebService当然最好是使用Web引用的方式了。毕竟WCF是后来出的,说是兼容WebService,但是总归没有原生态的好。所以建议如果是WebService客户端引用一律用Web引用(好像是.NET2.0时就叫Web引用)。
操作步骤:删除之前的服务引用(如果有的话);点击服务引用,点击最底下的高级,点击兼容性中的web引用,输入你的webservice地址