使用WCF更新数据

        虽然基于Web Service 的SOAP和POST并不总是加载数据的理想机制,但它们仍然适合用于对方法的调用,特别是对复杂数据的输入或修改。使用WCF时,并不真正需要作出一区分——同样的WCF方法能够像简单XML终结点或SOAP终结点一样发布。服务层将完全由AJAX界面分开,既不需要改变服务中的代码,也不需要对AJAX或者任何其他客户端技术指定任何的约束。事实上,可以选择在一些替代的传输机制上发布WCF应用。例如MSMQ、TCP/IP,甚至SMTP。

        注意:
                 Wiki是为了便于在Web上进行沟通而开发的一种记事本类应用程序,其设计宗旨是能够高效、简便地使用。下例中同时建立一个知识基础应用来学习使用Wiki技术。更多                  关于Wiki的信息参见 http://en.wikipedia.org/wiki/Wiki

        建立简单的Web Service来记录应用状态的消息。首先,定义一个名叫WikilData的数据类,这个类是WCF服务的起始点——它定义了服务返回的消息。可以使用DataContract和DataMember属性来定义数据结构,在WikiData类中,使用DataContract属性来定义元素的命名空间,使用DataMember属性来定义XML序列元素(WikiData类的定义参见下面代码)。定义这个协议后,就能够编写任何针对这种数据格式的客户端应用。

    [DataContract(Name = "WikiData",
        Namespace = "ServiceOrientedAjax.Examples")]
    public class WikiData
    { 
        [DataMember]
        public string Title { get; set; }

        [DataMember]
        public string Body { get; set; }

    }

输出的格式如下:
<WikiData xmlns="ServiceOrientedAjax.Examples" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
  <Body>Hello WCF World!</Body> 
  <Title i:nil="true" /> 
  </WikiData>


        在定义了数据协议之后,下一步是实现服务。可以是用VS模板或者通过定义标有ServiceContract属性的类来创建服务。ServiceContract属性将这个类标记为WCF的服务实现。每一个作为Web Service终结点发布的方法都必须使用OperationContract属性进行标识。OperationContract属性与ASP.NET Web Service中使用的WebMethod相似,定义了一个通过WCF终结点发布的方法。
        由于定义具有DataContract属性的数据类WikiData,因此能够简单使用WikiData作为Get请求的返回类型以及Set操作的输入参数。下列程序定义了一个简单WCF服务,此服务使用上例中的wikiData数据协定。

  [ServiceContract(Namespace = "ServiceOrientedAjax.Examples")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service1 
    {
        [OperationContract]
        public void SetWiki(WikiData wiki)
        {
            HttpContext.Current.Application[wiki.Title] = wiki.Body;
        }

        [OperationContract]
        [WebGet]
        public WikiData GetWiki(string title)
        {
            WikiData wiki = new WikiData 
            { 
                Title=title,
                Body=(string)HttpContext.Current.Application[title] ?? "Hello WCF World!"
            };
            return wiki;
        }
    }

        在定义了WCF服务之后,需要在ASP.NET应用中通过服务文件(SVC文件)和web.config定义终结点。SVC文件时ASP.NET中用来激活WCF服务终结点的简单文本文件,该文件中应当包含一下对 Service1 WCF终结点的引用:
<%@ ServiceHost  Service="WcfServiceLibrary1.Service1" %>

        除了在SVC文件中定义服务终结点之外,还必须在web.config中定义终结点和行为。这些行为可以影响多个终结点,并且能够改变终端访问WCF终结点的方式。在这个例子中,定义了POX终结点以及包括enableWebScript在内的JSON-enable终结点。这些增加的行为可以通过behaviorConfiguration元素来启用。
        为了启用ASP.NET AJAX来为服务建立JavaScript代理类,可以指定能够映射到多个WCF终结点的enableWebScript行为。下面的例子定义了名为JsonBehavior的行为配置项(JsonBehavior 是随意选择的命名),其中包含着enableWebScript行为:
 <behavior name="JsonBehavior">
          <enableWebScript />
        </behavior>

        enableWebScript行为使用JavaScript对象符号来定义数据,将默认响应从XML格式转换JSON格式。在手工处理数据并且不能使用XSLT转换时,这种格式比较易于处理。由于WCF从实现中抽象出终结点行为,因此可以在web.config内定义XML终结点和JSON终结点而不会导致服务的任何改变。非常重要的一点是:这种映射通过配置而不是服务来开发完成。
        为了定义一个负载的提供JSON数据的终结点,可以使用web.config将终结点映射到行为配置上。例如将一个附加的终结点(这是一个具备与Service.svc终结点同样实现的JSON-enable终结点)映射到Service.svc/json上。要定义这个终结点,需要使用一个子终结点元素来创建服务元素,终结点元素为服务定义了地址、行为配置、绑定以及协定。终结点的地址与激活WCF服务的.svc文件相关,behaviorConfiguration定义了终结点的附加行为。接下来的例子为Service1定义了服务中金额的,同时含有一个映射到/json、使用JsonBehavior配置的附加终结点。
 <services>
      <service name="WcfServiceLibrary1.Service1" behaviorConfiguration="Global">
        <endpoint address="" behaviorConfiguration="PoxBehavior"
        binding="webHttpBinding" contract="WcfServiceLibrary1.Service1" />
        <endpoint address="json" behaviorConfiguration="JsonBehavior"
        binding="webHttpBinding" contract="WcfServiceLibrary1.Service1" />
      </service>
    </services>

         当通过具有enableClientScipt行为的终结点访问服务时,上面的数据协定会输出如下的JSON数据类:
{"wiki":{"Title":"default","Body":"Hello WCF World!"}}

        这个JSON格式数据流包含着与数据协定定义的XML输出相同的内容。由于在脚本中,JSON流比较容易使用,因此如果你不使用XSLT转换器,Microsoft将选择它作为脚本激活的Web Service的默认行为。
        由于已经具备了在web.config中为/json终结点定义的enableWebScript行为,ASP.NET AJAX运行环境会为服务生产一个JavaScript代理,这个代理能够调用WCF服务并获取相应。为了手工检查JavaScript代理,要使用WCF终结点并在URL后面加上/jsdebug开工选项,例如: http://localhost/ajaxfundamentals/simpleservice.svc/json/jsdebug 。代理中会含有通过ASP.NET AJAX JavaScript框架调用Web Service的正确的JavaScript语法细节,包括用来调用和索引数据的序列化对象,此时,你所需要了解的就是直接调用的实例方法。对于每一个Web Service操作,在方法的参数中应当添加 onSuccess  、onFailed 以及 userContext。由于所有的网络调用都是以异步方式的,因此必须为响应传递回调句柄。尽管能够将任意对象作为用户上下文进行传递,但通常userContext对象是原样传递给公共代理方法,包括GetWiki方法和SetWiki方法。实际的代理中包含更多的代码,但通常你需要调用的方法是对于公共服务方法的JavaScript函数。

 
SetWiki:function(wiki,succeededCallback, failedCallback, userContext) {
/// <param name="wiki" type="ServiceOrientedAjax.Examples.WikiData">WcfServiceLibrary1.WikiData</param>
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="userContext" optional="true" mayBeNull="true"></param>
return this._invoke(this._get_path(), 'SetWiki',false,{wiki:wiki},succeededCallback,failedCallback,userContext); },
GetWiki:function(title,succeededCallback, failedCallback, userContext) {
/// <param name="title" type="String">System.String</param>
/// <param name="succeededCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="failedCallback" type="Function" optional="true" mayBeNull="true"></param>
/// <param name="userContext" optional="true" mayBeNull="true"></param>
return this._invoke(this._get_path(), 'GetWiki',true,{title:title},succeededCallback,failedCallback,userContext); }


        在引用ASP.NET AJAX生成的JavaScript代理类后,才能在AJAX应用中使用这段代码,这就需要在Service节点中使用ScriptManager控件,定义对Service.svc的引用。为了增加ServiceReference,需要把带有Path参数的ServiceReference加到WCF终结点中,如下所示:

 <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services>
            <asp:ServiceReference Path="~/Service.svc/json" /></Services>
    </asp:ScriptManager>

下面是整体的程序清单:
HTML界面:
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <asp:ScriptManager ID="ScriptManager1" runat="server">
        <Services>
            <asp:ServiceReference Path="~/Service.svc/json" /></Services>
    </asp:ScriptManager>
    <div id="MainContent" οnclick="editMessage">
        Loading....
    </div>
    <br />
    <span style="border:solid 1px silver;" id="editButton" οnclick="editMessage();">
        Edit
    </span>
    <div id="EditorRegion" style="display:none;">
        <textarea id="TheEditor" rows="10" cols="10">
        </textarea>
        <br />
        <span style="border:solid 1px silver;" οnclick="save();">
            Save
        </span>
    </div>
    </form>

    <script language="javascript" type="text/javascript">

        var wikiName = 'default';

        function OnAjaxLoad() {
            var userContext = new Object();
            ServiceOrientedAjax.Examples.Service1.GetWiki(wikiName, getMessageSuccess, onMessageFailure, userContext);
        }

        function editMessage() {
            $get('EditorRegion').style.display = '';
            $get('editButton').style.display = 'none';
            $get('MainContent').style.display = 'none';
            $get('TheEditor').value = $get('MainContent').innerHTML;
            $get('TheEditor').enabled = true;
        }

        function getMessageSuccess(wikiData, userContext) {
            var EditorRegion = $get('EditorRegion');
            EditorRegion.style.display = 'none';
            var content = $get('MainContent');
            content.innerHTML = wikiData.Body;
            content.style.display = '';
            $get('editButton').style.display = '';
        }

        function save() {
            var msg = $get('TheEditor').value;
            var userContext = new Object();
            userContext.msg = msg;
            userContext.title = wikiName;
            var wiki = new Object();
            wiki.Title = wikiName;
            wiki.Body = msg;
            ServiceOrientedAjax.Examples.Service1.SetWiki(wiki, onSaveSuccess, onMessageFailure, wiki);
            $get('TheEditor').enabled = false;
        }

        function onSaveSuccess(response, wiki) {
            getMessageSuccess(wiki, null);
        }

        function onMessageFailure(ex, userContext) {

            var EditorRegion = $get('EditorRegion');
            EditorRegion.style.display = 'none';
            var content = $get('MainContent');
            content.innerHTML = ex.get_message();
            content.style.display = '';
        }

        Sys.Application.add_load(OnAjaxLoad);
    </script>
</body>
</html>

WCF服务类:
using System;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.ServiceModel.Web;
using System.Web;
using System.Runtime.Serialization;

namespace WcfServiceLibrary1
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
    [ServiceContract(Namespace = "ServiceOrientedAjax.Examples")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class Service1 
    {
        [OperationContract]
        public void SetWiki(WikiData wiki)
        {
            HttpContext.Current.Application[wiki.Title] = wiki.Body;
        }

        [OperationContract]
        [WebGet]
        public WikiData GetWiki(string title)
        {
            WikiData wiki = new WikiData 
            { 
                Title=title,
                Body=(string)HttpContext.Current.Application[title] ?? "Hello WCF World!"
            };
            return wiki;
        }
    }

    [DataContract(Name = "WikiData",
        Namespace = "ServiceOrientedAjax.Examples")]
    public class WikiData
    { 
        [DataMember]
        public string Title { get; set; }

        [DataMember]
        public string Body { get; set; }

    }
}


Web.config 配置:
<system.serviceModel>
    <behaviors>
      <endpointBehaviors>
        <behavior name="PoxBehavior">
          <webHttp />
        </behavior>
        <behavior name="JsonBehavior">
          <enableWebScript />
        </behavior>
      </endpointBehaviors>
      <serviceBehaviors>
        <behavior name="Global">
          <serviceDebug includeExceptionDetailInFaults="true"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <!--   -->
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />

    <services>
      <service name="WcfServiceLibrary1.Service1" behaviorConfiguration="Global">
        <endpoint address="" behaviorConfiguration="PoxBehavior"
        binding="webHttpBinding" contract="WcfServiceLibrary1.Service1" />
        <endpoint address="json" behaviorConfiguration="JsonBehavior"
        binding="webHttpBinding" contract="WcfServiceLibrary1.Service1" />
      </service>
    </services>
    
  </system.serviceModel>


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值