jQuery Ajax调用WCF服务详细教程


Posted in Javascript onMarch 31, 2015

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

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

首先,说说搭建过程。

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

jQuery Ajax调用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);
  }
}

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

jQuery Ajax调用WCF服务详细教程

由于我的服务需要支持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项目选择“发布”菜单项,在弹出窗口中的下拉列表中选择“新建配置文件”,输入配置文件名称,点击“确定”按钮后进入连接设置界面,如下:

jQuery Ajax调用WCF服务详细教程'

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

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

第七步,实测

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

jQuery Ajax调用WCF服务详细教程

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。

Javascript 相关文章推荐
JavaScript下通过的XMLHttpRequest发送请求的代码
Jun 28 Javascript
用Javascript实现Windows任务管理器的代码
Mar 27 Javascript
jQuery UI 实现email输入提示实例
Aug 15 Javascript
利用js(jquery)操作Cookie的方法说明
Dec 19 Javascript
javascript使用smipleChart实现简单图表
Jan 02 Javascript
JavaScript的jQuery库中ready方法的学习教程
Aug 14 Javascript
详解react关于事件绑定this的四种方式
Mar 09 Javascript
Webpack的dll功能使用
Jun 28 Javascript
mocha的时序规则讲解
Feb 16 Javascript
Vue.js 无限滚动列表性能优化方案
Dec 02 Javascript
用js编写留言板
Mar 17 Javascript
vue中实现点击变成全屏的多种方法
Sep 27 Javascript
JavaScript父子窗体间的调用方法
Mar 31 #Javascript
JavaScript操作cookie类实例
Mar 31 #Javascript
javascript实现简单的贪吃蛇游戏
Mar 31 #Javascript
javascript制作2048游戏
Mar 30 #Javascript
JavaScript模拟实现继承的方法
Mar 30 #Javascript
jQuery制作可自定义大小的拼图游戏
Mar 30 #Javascript
JS实现向表格中动态添加行的方法
Mar 30 #Javascript
You might like
绿山咖啡和蓝山咖啡
2021/03/04 新手入门
PHP 远程文件管理,可以给表格排序,遍历目录,时间排序
2009/08/07 PHP
探讨PHP JSON中文乱码的解决方法详解
2013/06/06 PHP
在windows平台上构建自己的PHP实现方法(仅适用于php5.2)
2013/07/05 PHP
Smarty变量用法详解
2016/05/11 PHP
Javascript在IE或Firefox下获取鼠标位置的代码
2009/12/18 Javascript
基于jquery实现的上传图片及图片大小验证、图片预览效果代码
2011/04/12 Javascript
js showModalDialog参数的使用详解
2014/01/07 Javascript
扒一扒JavaScript 预解释
2015/01/28 Javascript
Javascript中实现String.startsWith和endsWith方法
2015/06/10 Javascript
jquery实现鼠标滑过后动态图片提示效果实例
2015/08/10 Javascript
JS实时弹出新消息提示框并有提示音响起的实现代码
2016/04/20 Javascript
用js实现博客打赏功能
2016/10/24 Javascript
利用Js+Css实现折纸动态导航效果实例源码
2017/01/25 Javascript
Vue关于数据绑定出错解决办法
2017/05/15 Javascript
JavaScript创建对象的七种方式全面总结
2017/08/21 Javascript
Vuejs中使用markdown服务器端渲染的示例
2017/11/22 Javascript
angularjs 获取默认选中的单选按钮的value方法
2018/02/28 Javascript
手写Node静态资源服务器的实现方法
2018/03/20 Javascript
Swiper 4.x 使用方法(移动端网站的内容触摸滑动)
2018/05/17 Javascript
使用watch在微信小程序中实现全局状态共享
2019/06/03 Javascript
JS数组方法concat()用法实例分析
2020/01/18 Javascript
解决vue watch数据的方法被调用了两次的问题
2020/11/07 Javascript
js canvas实现五子棋小游戏
2021/01/22 Javascript
利用Psyco提升Python运行速度
2014/12/24 Python
简单介绍Python中的readline()方法的使用
2015/05/24 Python
python中文乱码不着急,先看懂字节和字符
2017/12/20 Python
浅谈Python在pycharm中的调试(debug)
2018/11/29 Python
python的移位操作实现详解
2019/08/21 Python
python读取配置文件方式(ini、yaml、xml)
2020/04/09 Python
python实现在内存中读写str和二进制数据代码
2020/04/24 Python
最新pycharm安装教程
2020/11/18 Python
python+selenium小米商城红米K40手机自动抢购的示例代码
2021/03/24 Python
机关作风整顿个人整改措施2014
2014/09/17 职场文书
财务统计员岗位职责
2015/04/14 职场文书
再见,2019我们不负使命;你好,2020我们砥砺前行
2020/01/03 职场文书