jQuery Ajax调用WCF服务详细教程

这两天在写基于WCF服务的后台框架,过程中遇到了一些挫折,经过努力全部解决了,在此分享给大家,使用的工具是Visual Studio 2013。

该后台需要支持通过json来传递和接收数据。

首先,说说搭建过程。

第一步:创建WCF服务应用程序项目WCF。

第二步,创建服务使用的数据类

using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using System.Runtime.Serialization;

namespace WCF
{
  [DataContract]
  [Table("TUser")]
  public class Person
  {
    [DataMember]
    public int ID { get; set; }

    [DataMember]
    [StringLength(100)]
    public string LoginName { get; set; }

    [DataMember]
    [StringLength(100)]
    public string Password { get; set; }

    [DataMember]
    [DataType(DataType.Date)]
    public DateTime CreateDate { get; set; }
  }
}

这里,由于我使用EF来与数据库交互,所以使用了Table、StringLength、DataType。若你未使用EF,可以不加这些。DataContract是用来标志当前类在序列化时需要参考DataMember属性,若不设DataContract或仅设置DataMember,则所有共有属性和字段全部序列化,否则,只对设置有DataMember的序列化。注意,DataContract和DataMember与反序列化无关,也就是说,当把一个json对象字符串传递给WCF服务时,不管该字段上是否有DataMember,都会被反序列化。

第三步:创建服务契约接口

如果你的服务仅仅用来提供Ajax等一些非WCF客户端访问的,那么是不需要接口的,把接口定义中的各种Attribute直接加在服务提供的类的定义上即可。但是为了能让程序可以通过服务接口来访问,那么必须使用接口,例如:前端MVC+后台WCF的架构形式。

using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Web;

namespace WCF
{
  [ServiceContract]
  public interface IPersonService
  {
    [OperationContract]
    [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
    Person CreatePerson(string loginName, string password);

    //服务功能2
    [OperationContract]
    [WebGet(RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
    bool CheckMan(string loginName);
  }
}

第四步,创建基于契约接口提供实际服务的类

由于我的服务需要支持Ajax,所以选择“WCF服务(支持Ajax)”一项,具体代码如下:

using System;
using System.Collections.Generic;
using System.ServiceModel.Activation;

namespace WCF
{
  [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
  public class PersonService : IPersonService
  {
    public Person CreatePerson(string loginName, string password)
    {
      return new PersonBLL().CreatePerson(loginName,password);
    }

    public bool CheckMan(string loginName)
    {
      return new PersonBLL().CheckMan(loginName);
    }
  }
}

上述的PersonBLL是用来实际处理数据的业务逻辑层,有兴趣的伙伴们可以自己写个简单的实现。

第五步,创建网页客户端。

在此为了避免处理跨域问题,故把网页post_get_test.html放在WCF项目下。

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <script type="text/javascript" src="jquery-1.10.2.js"></script>
  <script type="text/javascript" src="jqueryjson.js"></script>
  <title></title>
</head>
<body>
  <p>
    <input id="createPerson" type="button" value="POST_CreatePerson" /><br>
    <input id="checkMan" type="button" value="GET_CheckMan" /><br>

    <input type="text" id="loginName" />
    <input type="text" id="password" />
  </p>
  <script type="text/javascript">
    $(document).ready(function () {
      $('#createPerson').click(function () {
        $.ajax({
          type: "post",
          url: "personservice.svc/CreatePerson",
          data: '{"loginName":"' + $("#loginName").val() + '","password":"' + $("#password").val() + '"}',
          contentType: "application/json; charset=utf-8",
          dataType: "json",
          success: function (data) {
            alert("ID:" + data.d.ID + " Name:" + data.d.LoginName + " Password:" + data.d.Password + " CreateDate:" + data.d.CreateDate);
          },
          error: function (xhr) {
            alert(xhr.responseText);
          }
        });
      });

      $('#checkMan').click(function () {
        $.getJSON("PersonService.svc/CheckMan", 'loginname="' + $("#loginName").val() + '"',
          function (data) {
            alert(data.d);
          });
      });
    });
  </script>
</body>
</html>

建议在开发过程中采纳createPerson按钮调用方式来写,其可以通过error回调函数来反馈实际出错原因,方便调试。

第六步,发布WCF服务

右击WCF项目选择“发布”菜单项,在弹出窗口中的下拉列表中选择“新建配置文件”,输入配置文件名称,点击“确定”按钮后进入连接设置界面,如下:

'

我是发布在本机的IIS中,故选择Web Deply发布方法,同时,这里建议服务器和站点名称设置成:localhost和default web site/XXX,这里XXX可以由你自己定义个服务站点的名字(实际就是IIS默认站点的虚拟目录名称),这样,你的开发伙伴获取到该项目源码后,能发布到完全相同的环境中,避免由于环境的差异延伸出一系列问题。

设置完毕后,点击“验证连接”,出现绿色的钩钩,说明设置正确,点击“发布”即可。

第七步,实测

1、现在可以通过浏览器访问http://localhost/wcf/personservice.svc来确认服务器端是否部署成功,出现如下界面说明部署成功。

2、通过浏览器访问测试网页http://localhost/wcf/post_get_test.html来检查功能是否OK。

其次,下面说说我在搭建过程中出现的各种问题。

1、网页通过Ajax调用服务的CreatePerson方法时把方法类型写错了,POST写成了GET,结果系统报:405 (Method Not Allowed)。另外,根据微软官网中描述,若通过soap访问一个WCF WEB HTTP应用程序(使用 WebHttpBinding 和 WebHttpBehavior 的服务)也会出现405错误。

2、web.config文件中endpoint节点的contract属性配置错误,没有指向WCF.IPersonService,网页执行时报:500 (System.ServiceModel.ServiceActivationException);在用http://localhost/wcf/personservice.svc检验服务器端部署结果时,报:在服务“PersonService”实现的协定列表中找不到协定名称“VME.Contract.PersonService”。

这里需要说明的是若你的服务不是基于接口的,则endpoint的contract直接指向服务类即可。

3、在使用jQuery的ajax并以POST方式传值给服务器时,由于格式错误,报如下错误:500 (Internal Server Error),详细信息为:格式化程序尝试对消息进行反序列化时引发异常。正确的有两种处理方式:

1)以json格式对象的方式传递,例如:

代码如下:

{"loginName":"name","password":"pwd"}

这里要强调的是键值对中,键必须加双引号,且大小写必须与服务方法中的形参定义完全一样。
2)以json格式对象字符串的形式传递,具体如下:

POST方式传值

A)传入非对象参数:

代码如下:

{"loginName":"name","password":"pwd"}'

这里要强调的是键值对中,键必须加双引号,且大小写必须与服务方法中的形参定义完全一样,值应按如下规则设置:字符串加双引号。
B)传入对象参数:

代码如下:

var person = {};
person.LoginName = $("#loginName").val();
person.Password = $("#password").val();
var jsonPerson = '{"person":' + $.toJSON(person) + '}';

这里要强调的是对象属性名称的大小写必须与数据类的属性定义完全一致。

GET方式传值

A)传入非对象参数:

代码如下:

'loginname="name"'

B)传入对象参数:

代码如下:

var person = {};
person.LoginName = $("#loginName").val();
person.Password = $("#password").val();
var jsonPerson = 'person=' + $.toJSON(person);

最后,说说WCF调试。

1、建议首先通过访问http://localhost/wcf/personservice.svc的形式确认服务器端部署成功,再进行客户端和服务器端联调。

2、若需要代码从客户端运行开始直到服务器端运行进行联调,则必须使用同步调用,因此,使用jQuery的ajax时,必须将async设置为false。

(0)

相关推荐

  • C# yield在WCF中的错误使用(二)

    昨天写了<yield在WCF中的错误使用--99%的开发人员都有可能犯的错误[上篇]>,引起了一些讨论.关于yield关键字这个语法糖背后的原理(C#编译器将它翻译成什么)其实挺简单,虽然有时候因为误用它会导致一些问题,但是它本无过错.接下来,我们通过这篇短文简单地谈谈我所理解的yield. 目录 一.先看一个简单的例子 二.了解本质,只需要看看yield最终编译成什么 三.回到WCF的例子 一.先看一个简单的例子 我们现在看一个简单的例子.我们在一个Console应用中编写了如下一段简单的程

  • 总结C#动态调用WCF接口的两种方法

    如何使用 1.第一种方式比较简单,而且也是大家喜欢的,因为不需要任何配置文件就可解决,只需知道服务契约接口和服务地址就可以调用. 2.使用Invoke的方式,但是需要在调用客户端配置WCF,配置后在Invoke类里封装服务契约接口即可. 客户端调用DEMO //第一种方式 string url = "http://localhost:3000/DoubleService.svc"; IDoubleService proxy = WcfInvokeFactory.CreateServic

  • jQuery实现ajax调用WCF服务的方法(附带demo下载)

    本文实例讲述了jQuery实现ajax调用WCF服务的方法.分享给大家供大家参考,具体如下: 关于AJAX调用WCF服务分为跨域和不跨域两种方式,今天咱们先介绍下不跨域下的调用方法.DEMO是在VS2008写的. 经过测试与研究,发现AJAX调用WCF服务必须满足以下条件 1.wcf的通讯方式必须使用webHttpBinding 2.必须设置<endpointBehaviors>节点的值 3.服务的实现必须添加标记 复制代码 代码如下: [AspNetCompatibilityRequirem

  • C# WCF简单入门图文教程(VS2010版)

    在这个例子中我们将使用VS2010创建一个WCF服务,其中会了解[DataContract][ServiceContract]等特性. 内置的WCFSVCHost,并使用"WCF测试客户端"来测试我们创建的服务. 注意下面的所有类.接口及方法都添加了public的访问级别. 一.建立一个WCF服务库 创建一个WCF服务库项目 在解决方案中会自动为我们生成两个类文件"IService1.cs"和"Service1.cs". 这两个类文件是两个WCF

  • C# 一个WCF简单实例

    WCF实例(带步骤) 复制代码 代码如下: <xmlnamespace prefix ="o" ns ="urn:schemas-microsoft-com:office:office" /> 本篇转自百度文档,自己试过,确实可以用. 以订票为例简单应用wcf 新建一个wcf服务应用程序 在IService1.cs定义服务契约 复制代码 代码如下: namespace WcfDemo { // 注意: 如果更改此处的接口名称 "IService

  • 关于.NET/C#/WCF/WPF 打造IP网络智能视频监控系统的介绍

    OptimalVision网络视频监控系统 OptimalVision(OV)网络视频监控系统(Video Surveillance System),是一套基于.NET.C#.WCF.WPF等技术构建的IP网络视频监控系统.设计与实现该系统的初衷是希望在家用电脑中部署该系统,连接本地或局域网设备,通过浏览器或手机客户端浏览宝宝实时视频,也就是俗称的"宝宝在线"或"家庭看护". 但由于业余时间总是有限,完成系统中的服务.配置.采集.传输和桌面GUI部分后,继续完成后续

  • C# yield在WCF中的错误用法(一)

    在定义API的时候,对于一些返回集合对象的方法,很多人喜欢将返回类型定义成IEnumerable<T>,这本没有什么问题.这里要说的是另一个问题:对于返回类型为IEnumerable<T>的方法来说,我们可以使用yield return的方式来输出返回集合的元素.但是如果我们不了解yield 关键字背后的实现机制,很有可能造成很大的问题. 这是一个WCF相关的问题,我想99%的人都有可能会犯这样的错误--即使你对yield了解得非常透彻.闲话少说,我们通过一个简单的实例来说明这个问

  • jQuery ajax调用WCF服务实例

    恩,在由瘦客户端转换成胖浏览器端的"潮流"下,必然要使用JavaScript调用后台的各种服务. 屌丝所维护的产品通信都是使用的WCF服务,因此必然要学习这样的内容.借用jQuery强大的库,使用JavaScript访问WCF服务非常简便.同事研究了一个breeze库,那么屌丝就来试验一下ajax.这里把实现简单地记录以便马克一下,以后忘了就看这篇日志来作弊. 一.更改WCF服务的配置 默认情况下,WCF服务是不允许使用HTTP请求来访问的.我们需要将WCF服务的配置文件(注意如果有其

  • WinForm窗体调用WCF服务窗体卡死问题

    窗体启动会启动一个程序主线程,如果在From_Load()方法中调用服务,调用服务操作会阻塞主程序. 只需要将调用服务的操作放到其他线程中处理就可以解决这个问题. 比如: 复制代码 代码如下: Thread ServiceThread=null; public void TestForm_Load(object sender, EventArgs e) { CheckForIllegalCrossThreadCalls = false; ServiceThread = new Thread(ne

  • jquery调用wcf并展示出数据的方法

    首选创能wcf,代码很简单,如下: 复制代码 代码如下: using System; using System.Data; using System.ServiceModel; using System.ServiceModel.Activation; using System.ServiceModel.Web; using System.Web.Script.Services; [ServiceContract(Namespace = "")] [AspNetCompatibilit

随机推荐