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常考语句107条收集
Mar 09 Javascript
jQuery的实现原理的模拟代码 -5 Ajax
Aug 07 Javascript
JavaScript避免内存泄露及内存管理技巧
Sep 05 Javascript
浅谈Javascript变量作用域问题
Dec 16 Javascript
jquery实现浮动的侧栏实例
Jun 25 Javascript
js实现异步循环实现代码
Feb 16 Javascript
Angularjs的键盘事件的绑定
Jul 27 Javascript
Swiper自定义分页器使用详解
Dec 28 Javascript
关于Vue在ie10下空白页的debug小结
May 02 Javascript
详解js中Array的方法及技巧
Sep 12 Javascript
js实现中文实时时钟
Jan 15 Javascript
vue 里面的 $forceUpdate() 强制实例重新渲染操作
Sep 21 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
DOTA2 无惧惊涛骇浪 昆卡大型水友攻略
2020/04/20 DOTA
Optimizer与Debugger兼容性问题的解决方法
2008/12/01 PHP
Zend Framework教程之Zend_Db_Table表关联实例详解
2016/03/23 PHP
PHP的简单跳转提示的实现详解
2019/03/14 PHP
动态表格Table类的实现
2009/08/26 Javascript
jquery 学习之一 对象访问
2010/11/23 Javascript
动态创建script在IE中缓存js文件时导致编码的解决方法
2014/05/04 Javascript
jQuery实现拖拽效果插件的方法
2015/03/23 Javascript
JavaScript中innerHTML,innerText,outerHTML的用法及区别
2015/09/01 Javascript
基于javascript html5实现3D翻书特效
2016/03/14 Javascript
原生JS实现图片轮播与淡入效果的简单实例
2016/08/21 Javascript
微信小程序之仿微信漂流瓶实例
2016/12/09 Javascript
JS实现超简单的汉字转拼音功能示例
2016/12/22 Javascript
jQuery实现网页拼图游戏
2020/04/22 jQuery
javascript+css实现俄罗斯方块小游戏
2020/06/28 Javascript
使用Python设计一个代码统计工具
2018/04/04 Python
pycharm 在windows上编辑代码用linux执行配置的方法
2018/10/27 Python
Python字符串处理的8招秘籍(小结)
2019/08/13 Python
python实现飞机大战小游戏
2019/11/08 Python
基于jupyter代码无法在pycharm中运行的解决方法
2020/04/21 Python
HTML5实时语音通话聊天MP3压缩传输3KB每秒
2019/08/28 HTML / CSS
泰国时尚电商:POMELO Fashion
2020/03/11 全球购物
自考自我鉴定范文
2013/10/30 职场文书
《与象共舞》教学反思
2014/02/24 职场文书
企业优秀团员事迹材料
2014/08/20 职场文书
小学生感恩老师演讲稿
2014/08/28 职场文书
师德师风个人自我剖析材料
2014/09/27 职场文书
小学五年级语文上册教学计划
2015/01/22 职场文书
师德承诺书2015
2015/04/28 职场文书
奖励申请报告范文
2015/05/15 职场文书
经济纠纷起诉状
2015/05/20 职场文书
健康证明
2015/06/19 职场文书
2015少先队大队辅导员工作总结
2015/07/24 职场文书
敬老院活动感想
2015/08/07 职场文书
Pytorch使用shuffle打乱数据的操作
2021/05/20 Python
python中__slots__节约内存的具体做法
2021/07/04 Python