现在的位置: 首页 > 综合 > 正文

WCF中的REST架构二 (支持AJAX的WCF服务 – 创建服务)

2013年09月18日 ⁄ 综合 ⁄ 共 4048字 ⁄ 字号 评论关闭

我在昨天  的文章WCF中的 REST架构一(REST 概述)谈了REST的基本概要,并提出了从HI REST (高REST)到 LO REST (REST) RESTFULnessREST度)的概念。在今天的文章中,我将详细介绍大家可能最为熟悉的REST风格的 WCF 服务:支持AJAX的服务。此类服务应属于LO REST的范畴。现在很多人直觉地将“好”等同于“高大全”,因而低估了这种LO REST实现的价值。本篇将告诉你这决非事实,支持AJAXWCF服务是足够强大的。

解决方案的背景信息

我有一个底层工作已基本完整的
初始解决方案,大部分代码是作为12AJAX 客户库Webcast 系列的组成部分。提供这个初始解决方案的目的是为了让我更好地展现支持AJAX的WCF服务的强大能力,避免现场创建一个这样的服务然后再与AJAX 客户应用集成所需的冗长步骤(如何你认为我创建的范例应用乏善可陈,请试一下Supersefer,这是一个基于这个范例的希伯来文网上商店)。在这个初始解决方案中请特别注意两个ASP.Net AJAX 控件: Catalog.jsShoppingCart.js. 下面的截图就是这两个控件的显示



Catalog
控件是本篇的重要操作对象,它的任务是接受一个特定的数据结构,显示一页产品信息,作绑定用途,并在用户选中某样产品或者点击浏览控件的时候出发消息,至于该控件是如何与宿主页(Catalog.aspx)交互,大家可以在前面提到的Webcast系列中找到。就本篇而言,我们只要关注Catalog.aspx(宿主页)中的下列代码片段,里面有一个GetData() 方法。等我们实现了WCF服务之后,就在这个方法里调用它。我们会给WCF服务传入诸如startIndex(起始索引)和pageSize(页的大小)之类的参数(服务的返回数据将是指定页数的产品信息), 以及几个回调方法(服务调用成功或失败后被回调)。下面也给出了调用成功的回调方法。该方法直接获取了指向catalog控件的引用($get asp.netAJAX中用来指向一个控件)。然后它将设定当前页的索引值,再用传入回调函数的数据,也就是我们的WCF有效荷载,来设定productInfo属性。最后,该函数调用控件的dataBind方法,这个方法直接基于存储在productInfo属性中的数据做了一些DOM注入。

 

添加服务

添加一个支持AJAX WCF 服务相当简单。第一步就是使用'AJAX-enabled WCF Service'模板添加服务。过程如下:在Solution Explorer里面选择”Add New Item’ > 选择'AJAX-enabled WCF Service' > 将其命名为 CatalogService.cs > 点击 ‘Add’.

模板看起来相当神奇,其实它不过是添加了一些特定的文件,并更改了另一些文件(通常是*.config文件)而已。如果你是按照我的步骤,那么这个模板做了下列事情:
1.       在项目根目录下添加CatalogService.svc文件
2.       app_code目录下添加CatalogService.cs文件
3.       web.config内配置服务

分析一下生成的文件

我们来看一下上面模板生成的文件并稍加讨论:

CatalogService.svc
<%@ ServiceHost     Language="C#"
                   
Debug="true"
                   
Service="CatalogService"
                    
CodeBehind="~/App_Code/CatalogService.cs" %>

*.svc文件可以类比于*.asmx文件。如果该服务在IIS或者WAS上运行,这个文件就作为服务的可定位资源。换句话说,*.svc 就是你服务的的基址。这个文件里我们只需注意两个属性:首先是Service属性,该属性被设为实现该服务的CLR类型名(你可以在app_code目录下的CatalogService.cs中找到该类型)。第二个就是指向实现文件的CodeBehind属性。

你无需修改svc 文件的内容,我只是为了向你展示该文件就是作为服务的base地址。

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

如果熟悉WCF,你一定知道WCF的配置是位于system.serviceModel节点下。你会看到3个子节点:behaviors, serviceHostingEnvironmentserivces:
1.  Services: 文件内已经有一个名为CatalogService的服务,与实现服务的类名一致。在Service节点下,你可以看到Endpoint,它包含了服务的ABCsAddress(地址) binding (绑定)和contract (协定).
    a.  Address: 你会发现地址是空的 ,不必担心,因为svc文件会作为基
    b.  Binding: webHttpBindingWCF3.5提供的可以让服务以REST方式发布的新型绑定。这个绑定有两种模式,你可以通过特定的终结点行为来指定模式(通过设定behaviorConfiguration)
    c.  Contract: contract指定了WCF服务提供的功能。该属性被设为一个已经定义好的服务协定。要定义一个服务协定,你可以用ServiceContract修饰一个接口或者类。被ServiceContract修饰的接口或者类中,所有由OperationContract修饰的方法将被作为服务的操作暴露给客户。一般来说用接口做服务协定是更好的做法,这样做的好处是分离了协定与具体实现。 但在我们使用的模板中却使用了类的方法,也就是说,接口是从类自动推断出来的(接口推断)。 
    d.  BehaviorConfiguration: 对于webHttpBinding, 你需要将该属性设为一个拥有webHttpenableWebScript子节点的终结点行为。

2. 
Behaviors: behaviors加入到服务或者服务终结点的目的在于改变runtime的默认行为或者加入定制的扩展。你会发现我们使用的模板已经声明了一个名为CatalogServiceAspNetAjaxBehavior的终结点行为该行为有一个enableWebScript 元素。enableWebScript是两种可能的终结点行为之一,另一种就是webHttp。事实上enableWebScriptwebHttp用来提供AJAX 功能(比如生成客户端代理)的子类

3. 
ServiceHostingEnvironment:
ASP.Net运行的WCF服务的默认配置是让两者互不干扰 例如,ASP.NET runtime 不参与WCF请求的处理. WCF服务也不能使用ASP.NET context session 这样的功能. 而我们这里的配置是将aspNetCompatibilityEnabled 设为true, 在这种设置下WCF请求就会加到ASP.Net 的请求流水线里了

*要使WCF支持REST,只要在该配置文件中注意最重要的两点:1binding应设为webHttpBinding 2) endpoint behavior要设定为webHttpenableWebScript

CatalogService.cs
 
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)]
public class CatalogService
{
    // Add [WebGet] attribute to use HTTP GET
    [OperationContract]
   
public void DoWork()
    {
        // Add your operation implementation here
        return;
    }
    // Add more operations here and mark them with [OperationContract]
}

在这里我们就真得做点儿事儿了。如果已经读了上面的内容,你应该已经注意到我们已经用接口推断的方法定义了的服务协定,就是说用ServiceContract

抱歉!评论已关闭.