注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Alex的博客

 
 
 

日志

 
 

ajax调用WCF  

2011-05-11 14:25:08|  分类: 编程 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、 简介

    在过去的几年中,Web服务一直在大做宣传,宣称提供了跨平台的服务。实现证明,Web服务的确支持在不同的平台上使用客户机和服务器。此外,通过定义一个WSDL契约,可以提前计划版本的改变,从而有效地避免已有的客户机和服务器可能出现的崩溃。目前,微软ASP.NET是用于开发Web服务的重要技术之一。Web服务在ASP.NET和JAVA等平台上的广泛应用是Web服务技术生命力鲜活的有力佐证。
    然而,在ASP.NET Web服务中存在的问题是,它使用的是HTTP协议(通过WSE 2.0,也可以使用TCP信道),用SOAP协议进行XML串行化的速度不够快,一些扩展功能很难使用。Web服务技术的确在提供跨平台服务方面迈出了重要的一步,但是在建立涉及到许可的可交互操作服务、需要保证消息的传输、要求独立于平台的身份验证、授权和机密性等方面,仅仅依赖于Web服务已经表现得相当吃力。
    随着.NET 3.0框架的正式推出,WCF(Windows通信基础)闪亮登场。WCF的核心目的是,允许程序与同一台计算机或网络上的或跨越互联网的其它程序实现通讯。此模型把以前在网络上使用服务的四种重要技术即Web服务、.NET远程技术、分布式事务和消息队列统一到单个面向服务的编程模型中,从而实现真正意义上的分布式计算。WCF代表了微软通信技术的未来发展方向。因此,从原则上讲,凡是需要使用上面四种技术的开发都可以使用WCF代之。
    尽管如此,现实的Web开发环境不可能使开发人员全部选择最新的WCF通信技术。也就是说,基于ASP.NET 2.0 Web服务技术的应用目前乃到将来几年中仍会占有相当的市场份额。
    ASP.NET AJAX框架极大地简化了从ASP.NET应用程序中调用本地服务乃至远程服务的操作,甚至提供了许多内置的服务器服务,例如用户身份验证服务和用户个性化服务等。
    在以前的文章中,我们曾经探讨过如何在ASP.NET 2.0应用开发中使用ASP.NET AJAX框架实现Web服务的方便调用。在本文中,我们将通过一个简单的例子探讨如何在ASP.NET 3.5应用开发中使用ASP.NET AJAX框架(此框架的核心组件已经内置于ASP.NET 3.5中)实现对于新一代WCF服务的调用。
    【注意】在.NET框架 3.5以前,WCF中并没有实现对于JSON数据的内置支持。如今,随着.NET框架 3.5的正式推出,WCF已经实现了对于JSON串行化与非串行化的支持。现在的WCF服务可以根据开发需要有选择地输出JSON,而不是和以前那样仅能支持SOAP模式封装的数据。


二、 创建示例网站

    启动Visual Studio 2008并选择“ASP.NET Web Site”模板新创建一个示例网站AJAXWCFTest1,同时选择Visual C#作为内置支持语言,如图1所示。在此工程中,我们将添加一个WCF(Windows通信基础)服务来测试从客户端以AJAX(异步)方式调用这个WCF服务。
    ajax调用WCF - Alex - Alex的博客
    图1 使用VS2008构建支持WCF服务的AJAX ASP.NET网站
    注意,在ASP.NET 3.5中已经内置了对于ASP.NET AJAX框架三大组成之一的核心部分(即Extensions)的支持。而要进行ASP.NET AJAX客户端中心型编程或应用ASP.NET AJAX Control Toolkit组件,则还需要另行安装与引用相应的程序集和脚本。


三、 添加WCF服务

    现在,我们来学习如何在前面的ASP.NET网站中添加一个支持AJAX功能的WCF服务。为此,请右击上面的示例网站AJAXWCFTest1并选择“Add New Items…”,在随后出现的“Add New Items”对话框中选择“AJAX-Enabled WCF Service”模板添加一个新的WCF服务并命名为TimeService。
    ajax调用WCF - Alex - Alex的博客
    图2 添加支持AJAX技术的WCF服务
   
    通过上面的操作后,你会发现Web网站中添加了一个服务端点(即timeservice.svc)以及与之相联系的位于文件夹App_Code下的Code-behind文件timeservice.cs。此外,还注意到,配置文件web.config也被修改以便为刚刚创建的WCF服务提供相应的注册和发现信息。
    现在创建的这个TimeService类中已经隐含地描述了所定义WCF服务的契约及其显式实现。注意,其中的ServiceContract和OperationContract属性承担了与以前的WCF版本编程中同样的角色。另外,为了简化起见,在此没有使用接口定义契约。   


ajax调用WCF - Alex - Alex的博客using System; ajax调用WCF - Alex - Alex的博客using System.Runtime.Serialization; ajax调用WCF - Alex - Alex的博客using System.ServiceModel; ajax调用WCF - Alex - Alex的博客using System.ServiceModel.Activation; ajax调用WCF - Alex - Alex的博客using System.ServiceModel.Web; ajax调用WCF - Alex - Alex的博客 ajax调用WCF - Alex - Alex的博客[ServiceContract (Namespace = "Samples.Services")] ajax调用WCF - Alex - Alex的博客[AspNetCompatibilityRequirements( ajax调用WCF - Alex - Alex的博客RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)] ajax调用WCF - Alex - Alex的博客public class TimeService ajax调用WCF - Alex - Alex的博客ajax调用WCF - Alex - Alex的博客...{ ajax调用WCF - Alex - Alex的博客[OperationContract] ajax调用WCF - Alex - Alex的博客public DateTime GetTime() ajax调用WCF - Alex - Alex的博客ajax调用WCF - Alex - Alex的博客...{ ajax调用WCF - Alex - Alex的博客return DateTime.Now; ajax调用WCF - Alex - Alex的博客} ajax调用WCF - Alex - Alex的博客[OperationContract] ajax调用WCF - Alex - Alex的博客public string GetTimeFormat(string format) ajax调用WCF - Alex - Alex的博客ajax调用WCF - Alex - Alex的博客...{ ajax调用WCF - Alex - Alex的博客return DateTime.Now.ToString(format); ajax调用WCF - Alex - Alex的博客} ajax调用WCF - Alex - Alex的博客}

    注意到,上面的TimeService类共暴露了两个公共端点,分别是GetTime和GetTimeFormat。
到达上面接口中方法的端点定义于一个SVC文件中。下面给出了文件timeservice.svc的内容:
<%@ ServiceHost Language="C#"
Debug="true"
Service="TimeService"
CodeBehind="~/App_Code/TimeService.cs" %>
这个服务宿主(ServiceHost)指明了实现该服务使用的语言以及相应的源文件的位置,最后通过Service属性标识所使用的契约名字。
在正式开始测试这个服务前还有最后一项工作就是在宿主ASP.NET应用程序的配置文件web.config中注册上面这个WCF服务。下面展示了配置文件web.config中的相关配置节的内容:  


<system.serviceModel><behaviors><endpointBehaviors><behavior name="TimeServiceAspNetAjaxBehavior"><enableWebScript /></behavior></endpointBehaviors></behaviors><serviceHostingEnvironment aspNetCompatibilityEnabled="true" /><services><service name="TimeService"><endpoint address="" behaviorConfiguration="TimeServiceAspNetAjaxBehavior" binding="webHttpBinding" contract="TimeService" /></service></services></system.serviceModel>

    注意,上面的配置内容是随着WCF服务的创建由系统自动生成的。
    在此,首先针对前面WCF服务中的所有端点注册一个行为列表。通过这种方式,为WCF服务TimeServiceAspNetAjaxBehavior定义了一个行为并且指出它使用客户端脚本经由HTTP Web协议接受请求。从逻辑上分析,上面的enableWebScript元素与ASP.NET Web服务中用于修饰Web服务类的ScriptService属性是一致的。
    然后,需要枚举宿主于当前ASP.NET应用程序中的所有WCF服务。注意,上面的web.config文件中仅展示了一个名字为TimeService的服务,它的一个端点使用了TimeService契约和webHttpBinding绑定模型。


四、 关于测试WCF服务的问题

    在以前的ASP.NET AJAX Web服务编程中,一旦创建完Web服务,我们一般会按F5键先测试Web服务。直到没有问题后,我们再在Web页面中调用该Web服务。
    但是,对于新的WCF服务而言,当你按F5键试图运行相应的WCF服务时,浏览器中会给出一个如图3所示的警告性提示。
   
    ajax调用WCF - Alex - Alex的博客
        图3 示例程序运行时刻快照,点击页面中的按钮以WCF服务方式从服务器端异步取得当前时间信息 。
    根据图3中页面提示,要以类似于以前测试Web服务的方式测试WCF服务,需要经过页面中的三步配置。之后,才能实现这样的测试功能。尽管如此(略嫌麻烦些),在应用WCF服务之前先行测试还是极有必要的,恕在此不再赘述。


五、 调用WCF服务

    上面的服务定义与配置应该算是干净利索的。那么,现在我们来看一下分析从一个客户端ASP.NET页面中的<script>节中来使用此WFC服务呢?其实,从页面开发者角度来看,调用WCF服务的操作步骤与调用一个Web服务所要求的步骤没有太大的区别。
第一步是使用ASP.NET AJAX框架的脚本管理器控件ScriptManager中的SVC端点注册所要引用的WFC服务,如下所示:
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Services>
<asp:ServiceReference Path="~/TimeService.svc" />
</Services>
</asp:ScriptManager>
    当处理上面的标记时,ScriptManager控件将触发器额外的请求用以生成和下载指定的WCF服务的JavaScript代理类。然后,客户端页面将使用这个代理类实现相应的调用。
    注意到,代理类的名字是根据WCF服务的命名空间进行命名的,具体是由ServiceContract属性的Namespace参数进行声明的。如果你保留此参数为其缺省值(即Tempuri.org),那么该代理类的名字为Tempuri.org.TimeService。在本例中,我们的定义如下所示:
[ServiceContract(Namespace="Samples.Services")]
    第二步,我们使用下列JavaScript来调用前面WCF服务中定义的方法GetTimeFormat:    


ajax调用WCF - Alex - Alex的博客ajax调用WCF - Alex - Alex的博客<script language="javascript" type="text/javascript">... ajax调用WCF - Alex - Alex的博客function getTime() ajax调用WCF - Alex - Alex的博客ajax调用WCF - Alex - Alex的博客...{ ajax调用WCF - Alex - Alex的博客Samples.Services.TimeService.GetTimeFormat( ajax调用WCF - Alex - Alex的博客"dd-mm-yyyy [hh:mm:ss]", onMethodCompleted); ajax调用WCF - Alex - Alex的博客} ajax调用WCF - Alex - Alex的博客 ajax调用WCF - Alex - Alex的博客function onMethodCompleted(results) ajax调用WCF - Alex - Alex的博客ajax调用WCF - Alex - Alex的博客...{ ajax调用WCF - Alex - Alex的博客$get("lblCurrentTime").innerText = results; ajax调用WCF - Alex - Alex的博客 ajax调用WCF - Alex - Alex的博客} ajax调用WCF - Alex - Alex的博客</script> ajax调用WCF - Alex - Alex的博客………… ajax调用WCF - Alex - Alex的博客</head> ajax调用WCF - Alex - Alex的博客<body> ajax调用WCF - Alex - Alex的博客<form id="form1" runat="server"> ajax调用WCF - Alex - Alex的博客<asp:ScriptManager ID="ScriptManager1" runat="server"> ajax调用WCF - Alex - Alex的博客<Services> ajax调用WCF - Alex - Alex的博客<asp:ServiceReference Path="~/TimeService.svc" /> ajax调用WCF - Alex - Alex的博客</Services> ajax调用WCF - Alex - Alex的博客</asp:ScriptManager> ajax调用WCF - Alex - Alex的博客<div class="style3" ajax调用WCF - Alex - Alex的博客style="border-style: double; border-color: #008000; "> ajax调用WCF - Alex - Alex的博客<span class="style1">在</span><span class="style1" lang="EN-US">ASP.NET 3.5 AJAX</span><span ajax调用WCF - Alex - Alex的博客class="style1">开发中调用</span><span class="style1" lang="EN-US">WCF</span><span ajax调用WCF - Alex - Alex的博客class="style1">服务<br /> ajax调用WCF - Alex - Alex的博客</span> ajax调用WCF - Alex - Alex的博客</div>ajax调用WCF - Alex - Alex的博客 ajax调用WCF - Alex - Alex的博客</form> ajax调用WCF - Alex - Alex的博客<input id="Button1" type="button" value="取得当前服务器端时间" onclick="getTime()" /> ajax调用WCF - Alex - Alex的博客<div id="lblCurrentTime"> ajax调用WCF - Alex - Alex的博客 ajax调用WCF - Alex - Alex的博客</div> ajax调用WCF - Alex - Alex的博客</body> ajax调用WCF - Alex - Alex的博客

    这里JavaScript代理类是由静态方法组成的,它们的名字和语法声明与WCF服务端点的原型是完全相匹配的。另外,类似于ASP.NET AJAX Web服务,每一个JavaScript代理方法也支持一组额外的参数,这是一组回调函数,用于处理调用过程中可能会出现的成功和失败,在此不再赘述。

六、 观察运行结果
    现在,按F5键运行上面的示例程序。顺利的话,你会观察到如图4所示的运行时刻快照。
    
    ajax调用WCF - Alex - Alex的博客
    图4 示例程序运行时刻快照,点击页面中的按钮以WCF服务方式从服务器端异步取得当前时间信息
    程序运行后,点击页面上的按钮“取得当前服务器端时间”即可以异步方式取得服务器端以WCF服务方式提供的当前时间数据。类似于以前的使用ASP.NET AJAX对Web服务的调用方式,你也可以在浏览器地址栏中输入http://localhost:1635/AJAXWCFTest1/TimeService.svc/jsdebug来观察ASP.NET AJAX框架生成的客户端代理类,如图5所示。
    ajax调用WCF - Alex - Alex的博客
        图5 观察ASP.NET AJAX框架为WCF服务生成的客户端代理类
   
    遗憾的是,本文示例并没有在FireFox 2.0下调试通过(程序启动后,点击按钮没有任何现象),但是却可以照旧观察到如图4所示的ASP.NET AJAX框架为WCF服务生成的客户端代理类。
    至此,我们已经从一个页面开发者的角度简要地介绍了WCF服务以及如何通过ASP.NET AJAX的服务器端控件ScriptManager调用WCF服务。接下来,我们来分析ASP.NET对于WCF服务与ASMX服务之间兼容性的支持问题。


七、 WCF服务与ASMX服务的兼容性

    根据前面的操作得知,当为ASP.NET AJAX程序创建一个新的WCF服务时,默认情况下该服务类前面使用AspNetCompatibilityRequirements属性进行修饰。现在,我们来作一下简要分析。
[ServiceContract]
[AspNetCompatibilityRequirements(
RequirementsMode=AspNetCompatibilityRequirementsMode.Allowed)]
public class TimeService
{
……
}
   
    虽然在设计上可以进行独立传输,但当应用于一个ASP.NET AJAX应用程序环境下时,WCF服务实际上可以工作在一种十分类似于ASMX服务的方式下。借助于这个AspNetCompatibilityRequirements属性,我们可以指示WCF使用与ASMX服务相同的模型进行工作。实际情况下,这个设置指示当激活一个WCF服务时,运行时刻将对声明的端点进行检查并确保它们都使用了Web HTTP绑定模型。
    与ASMX服务的良好兼容性可以使得在WCF服务中访问ASP.NET对象例如HttpContext对象以及其它内在的ASP.NET对象完全有可能。
    注意,要实现WCF服务与ASMX服务的兼容性至少要实现两点。第一,在配置文件web.config中,需要进行类似如下的声明式定义:
<system.serviceModel>
:
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
</system.serviceModel>
    第二,开发者需要显式地选择一个给定WCF服务的兼容性方式,这是通过使用服务AspNetCompatibilityRequirements属性完成的。
八、 总结
    在ASP.NET AJAX应用程序中请求的服务要求必须进行相应的服务器端配置。归纳看来,在ASP.NET应用程序中,目前主要存在两种软件技术可以用来构建服务,即ASMX Web服务和WCF服务。其中,WCF服务已经包括了ASMX Web服务。但是,必须明确:AJAX通信要求使用JSON数据字符串实现数据在客户端与服务器的来回传输。在ASP.NET AJAX扩展1.0时代或者在ASP.NET 3.5中调整ASP.NET运行时刻使ASMX Web服务支持JSON是一项比较容易的任务。但是,针对更为丰富的WCF服务要求实现JSON数据格式的传输则要略微复杂一些。这也正是为什么仅仅在ASP.NET 3.5中才可以使用WCF构建AJAX后端服务的原因。

  评论这张
 
阅读(108)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018