Web服务和ASPNETWord文件下载.docx
《Web服务和ASPNETWord文件下载.docx》由会员分享,可在线阅读,更多相关《Web服务和ASPNETWord文件下载.docx(39页珍藏版)》请在冰豆网上搜索。
ASP.NETWeb服务使用起来比较简单,足以满足大多数需要,而
WindowsCommunicationFoundation(WCF)Web服务包含ASP.NETWeb服务的全部功
能,还添加了额外的功能。
WCF详解第43章。
C#高级编程(第7版)
E240
55.1SOAP
如前所述,SOAP是一个与Web服务交换数据的方法。
有关这项技术的书有很多,尤其是微软
公司决定在.NETFramework中采用这项技术之后,SOAP方面的书就更多了。
稍微考虑一下,可以
发现SOAP的工作原理和HTTP的工作原理比较相似,这非常有趣,但并不是必需的。
大多数情况下,
我们不必考虑与Web服务进行交换时所采用的格式,只要得到希望的结果就够了。
因此,本节不深入探讨SOAP的技术细节,而是给出一些简单的SOAP请求和响应,以便您对
SOAP有一个感性的认识。
假定要用下面的签名调用Web服务中的方法:
intDoSomething(stringstringParam,intintParam)
这条语句必需的SOAP标题和主体如下所示,最上面是Web服务的地址:
POST/SomeLocation/myWebService.asmxHTTP/1.1
Host:
hostname
Content-Type:
text/xml;
charset=utf-8
Content-Length:
length
SOAPAction:
"
http:
//tempuri.org/DoSomething"
<
?
xmlversion="
1.0"
encoding="
utf-8"
>
soap:
Envelopexmlns:
xsi="
//www.w3.org/2001/XMLSchema-instance"
xmlns:
xsd="
//www.w3.org/2001/XMLSchema"
soap="
//schemas.xmlsoap.org/soap/envelope/"
Body>
DoSomethingxmlns="
//tempuri.org/"
stringParam>
string<
/stringParam>
intParam>
int<
/intParam>
/DoSomething>
/soap:
Envelope>
length参数用于指定内容的总字节数,它的大小随着string和int参数中发送的值而变化。
Host
也是变化的,它取决于Web服务的位置。
上面代码引用的soap名称空间定义用于构建消息的各种元素。
通过HTTP发送上面的代码时,实
际发送的数据将有所不同(但是相关)。
例如,可以使用简单的GET方法调用上面的方法:
GET/SomeLocation/myWebService.asmx/DoSomething?
stringParam=string&
intParam=int
HTTP/1.1
这个方法的SOAP响应如下:
HTTP/1.1200OK
第55章Web服务和ASP.NET
E241
DoSomethingResponsexmlns="
DoSomethingResult>
/DoSomethingResult>
/DoSomethingResponse>
其中length参数的值根据int参数值的变化而改变。
此外,通过HTTP的实际响应也比较简单,例如:
intxmlns="
/int>
这是一种比较简单的XML格式。
如本节开始时所讨论的,有许多语法问题可以完全忽略。
只有在需要考虑语法时,语法才会变
得很重要。
55.2WSDL
WSDL可以完整地描述Web服务、可用的方法,以及调用这些方法的各种方式。
此外,虽然过
多地讨论WSDL的细节对我们并没有太多的好处,但对WSDL的总体理解却非常有用。
WSDL是另一种与XML完全兼容的语法。
WSDL通过可用的方法、这些方法所使用的类型、
通过各种协议(纯SOAP、HTTPGET等)发送给方法的请求消息和从方法中发送出的响应消息的格
式,以及上面规范的各种绑定,指定Web服务。
WDSL由各种客户端读取,而不只是.NET,还有
本章前言提及的MacromediaFlash。
WSDL文件中最重要的部分或许是类型定义部分。
这一部分使用XML架构描述数据交换的格
式,数据交换的格式要通过可使用的XML元素和元素之间的关系定义。
例如,上一节中的示例所使用的Web服务方法:
下面是为请求所做的类型声明:
definitionsxmlns:
http="
//schemas.xmlsoap.org/wsdl/http/"
//schemas.xmlsoap.org/wsdl/soap/"
s="
wsdl="
//schemas.xmlsoap.org/wsdl"
...othernamespaces...>
wsdl:
types>
s:
schemaelementFormDefault="
qualified"
targetNamespace="
elementname="
DoSomething"
complexType>
C#高级编程(第7版)
E242
sequence>
elementminOccurs="
0"
maxOccurs="
1"
name="
stringParam"
type="
string"
/>
intParam"
int"
/s:
element>
DoSomethingResponse"
DoSomethingResult"
schema>
/wsdl:
...otherdefinitions...
/definitions>
这些类型都是以前我们看到的SOAP和HTTP请求及响应所必需的,并且这些类型被绑定在文
件中的后期操作上。
所有这些类型都使用标准的XML架构语法指定,例如:
这个示例指定一个DoSomethingResponse元素,该元素包含一个子元素DoSomethingResult,这
个子元素包含了一个整数。
这个整数必须出现1次,即它必须包含在内。
如果可以访问Web服务的WSDL,就可以使用WSDL。
不久我们可以看到,对WSDL的使用
并不困难。
上面对SOAP和WSDL进行简短的讨论,接下来讨论如何创建和使用Web服务。
55.3Web服务
Web服务的讨论分为两个方面:
●创建Web服务,这一部分主要讨论如何编写Web服务和如何把它们放在Web服务器上。
●使用Web服务,这一部分主要讨论如何在客户端应用程序中使用Web服务。
55.3.1提供Web服务
把代码直接放到.asmx文件中或者从这些文件中引用Web服务类,都可以提供Web服务。
如同
ASP.NET页面一样,在VisualStudio.NET中创建Web服务也使用后一种方法,目的是把问题讲述第55章Web服务和ASP.NET
E243
得更清楚一些。
如图55-1所示,使用File|New|WebSite命令在C:
\ProCSharp\Chapter55目录下创建一个Web服
务项目PCSWebService1,此时系统会生成一组类似的文件,它们与创建Web应用程序项目时所生成
的一组文件相似,其位置选项也相同。
实际上,唯一的区别就是创建Web应用程序时生成的文件是
Default.aspx,而创建Web服务项目时生成的文件是Service.asmx,其代码隐藏是App_Code/Service.cs。
图55-1
Service.asmx中的代码如下所示:
%@WebServiceLanguage="
C#"
CodeBehind="
~/App_Code/Service.cs"
Class="
Service"
%>
它引用代码文件/App_Code/Service.cs。
下面的程序清单是生成的代码:
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Linq;
usingSystem.Web;
usingSystem.Web.Services;
[WebService(Namespace="
)]
[WebServiceBinding(ConformsTo=WsiProfiles.BasicProfile1_1)]
//ToallowthisWebServicetobecalledfromscript,usingASP.NETAJAX,
//uncommentthefollowingline.
//[System.Web.Script.Services.ScriptService]
publicclassService:
System.Web.Services.WebService
{
publicService()
//Uncommentthefollowinglineifusingdesignedcomponents
//InitializeComponent();
}
[WebMethod]
publicstringHelloWorld()
return"
HelloWorld"
;
代码段PCSWebService1\App_Code\Service.cs
可从
下载源代码C#高级编程(第7版)
E244
这段代码包含几个标准名称空间引用,并定义Web服务类Service(它在Service.asmx中引用),
Service类继承自System.Web.Services.WebService。
WebService属性指定Web服务的名称空间,它
允许客户端应用程序区分不同Web服务中同名的Web服务方法。
WebServiceBinding属性与Web服
务的交互操作性相关,如WS-IBasicProfile1.1规范中的定义所示。
简言之,这个属性可以声明,
Web服务为一个或多个Web方法支持标准的WSDL描述,或者像这个示例一样,指定一组新的
WDSL定义。
其中还有一个注释掉的ScriptService属性,如果取消注释,就可以使用ASP.NETAJAX
脚本调用Web方法。
现在可以在这个Web服务类上提供其他方法。
在添加可以通过Web服务访问的方法时,只需要把方法定义为public,并给方法提供WebMethod
属性。
这个属性仅把方法标记为可通过Web服务访问。
稍后将会学习返回类型和参数使用的类型,
现在用下面的方法替换自动生成的HelloWorld()方法。
publicstringCanWeFixIt()
Yeswecan!
"
现在编译该项目。
要检查是否一切正常工作,可用Ctrl+F5组合键运行应用程序,就会进入Web服务的测试页面,
如图55-2所示。
图55-2第55章Web服务和ASP.NET
E245
在浏览器中显示的大多数文本都说明把Web服务的名称空间设置为http:
//tempuri.org/。
这在开
发过程中不是问题,尽管以后应修改它(如Web页面中的文本所示)。
为此可以使用WebService属性,
但目前可以不修改它。
单击方法名称,可以得到SOAP请求和响应的信息,此外,还可以得到一个示例,说明了如何
通过HTTPGET和HTTPPOST方法获得请求和响应。
另外,也可以单击Invoke按钮,对方法进行
测试。
如果方法需要简单的参数,那么在这个窗体中也可以输入这些参数(如果方法需要较复杂的参
数,这个窗体就不允许以这种方式测试方法)。
这样,就可以看到方法调用所返回的XML:
stringxmlns="
Yeswecan!
<
/string>
这说明方法运行良好。
单击图55-2的浏览器屏幕上的ServiceDescription链接,可以查看Web服务的WSDL描述。
其
中最重要的部分是关于请求和响应的元素类型的描述:
targetNamespace="
CanWeFixIt"
complexType/>
CanWeFixItResponse"
CanWeFixItResult"
该描述文件比较长,除了包含服务的各种绑定之外,还可以包含请求和响应所需类型的描述。
1.对于Web服务可用的类型
Web服务可以用于交换表55-1中所示的类型。
表55-1
StringCharByte
BooleanInt16Int32
Int64UInt16UInt32
UInt64SingleDouble
注意,这个测试页面默认仅可用于本地计算机的调用者,即使Web服务驻留
在IIS(InternetInformationServices,Internet信息服务)中,也是如此。
E246
(续表)
GuidDecimalDateTime
XmlQualifiedNameclassstruct
XmlNodeDataSetenum
以上所有类型的数组都可以使用,因为它们都是泛型集合类型,如List<
string>
。
还要注意,只
能编组class和struct类型的公共属性和字段。
55.3.2使用Web服务
既然明白了如何创建Web服务,接下来就讨论如何使用它们。
为此需要在代码中生成一个知道
如何与给定Web服务进行通信的代理类。
这样,代码中对Web服务进行的任何调用都要通过这个
代理类,从表面看,这个代理类就等同于Web服务,代码也会认为我们有了Web服务的本地副本。
而实际的情况是有许多HTTP通信工作在进行,只是对我们屏蔽了其中的细节。
有两种方式可以完
成这项任务:
第一,可以使用WSDL.exe命令行工具;
第二,可以使用VisualStudio.NET中的Add
WebReference菜单选项。
从命令行中使用WSDL.exe时,它会根据Web服务的WSDL描述生成一个包含代理类的.cs文
件。
使用Web服务的URL来指定该文件,例如:
WSDLhttp:
//localhost:
53679/PCSWebService1/Service.asmx?
WSDL
这样就会在Service.cs文件中为上一节中的示例生成一个代理类。
这个代理类将以Web服务命
名,在这个示例中就是Service,该代理类包含一些方法,那些方法将可以调用与服务同名的方法。
在使用这个类时,只需把所生成的.cs文件添加到项目中,并在代码中使用下面的代码行:
ServicemyService=newService();
stringresult=myService.CanWeFixIt();
默认情况下,生成的类将放在根名称空间中,因此不需要使用using语句,但是,可以使用
WSDL.exe命令行选项/n:
namespace>
指定一个不同的名称空间。
虽然这项技术非常有效,但是,如果服务正处于开发或处于连续更改中,就比较麻烦。
当然,
为了在每次编译之前自动更新所生成的代理,这项技术可以用项目的构建选项执行,但是我们有更
好的方法。
在一个新的空白网站PCSWebClient1中,为上一节中的示例创建客户端(在C:
\ProCSharp\Chapter55
注意,这里和随后的例子使用默认的文件系统驻留Web应用程序。
为了使上面的
URL起作用,Web服务的VisualWebDeveloperWebServer必须正在运行。
这仍不能
保证Web服务的端口号(在这里是61968)仍相同。
这适合于演示,因为一般我们希望
Web服务驻留在固定的Web服务器(如IIS)上,否则就必须继续重新生成代理类。
确
保Web服务可用于测试的一种方式是在一个解决方案中包含多个Web站点。
E247
目录下),阐明这个更好的方法。
现在创建这个项目,添加Default.aspx页面,并在Default.aspx页面中
添加下面的代码:
formid="
form1"
runat="
server"
div>
asp:
LabelRunat="
ID="
resultLabel"
br/>
ButtonRunat="
triggerButton"
Text="
InvokeCanWeFixIt()"
/div>
/form>
代码段PCSWebClient1\Default.aspx