MSCRM 通过Ajax调用WCF服务
Call WCF Service from Dynamics CRM using AJAX
A couple of days back, I had one of my ex-colleagues call me regarding a problem he had been facing when making jQuery AJAX calls to JSON WCF Services from Dynamics CRM. I had encountered this same problem some years back, when I had just started my career as a CRM Developer. And since I toiled hard to find a resolution for that back then, it’s something that remains quite vibrant in my brain. I told him the solution only to get an appreciation the next day that it had worked for him. I was glad to have helped someone fix this without having to scour through the internet for solutions; and hence decided to put it up in my blog when a different friend of mine called me a few days back again with the same problem (except this time there was no Dynamics CRM involved). Now, to the problem. The problem was while making jQuery Ajax calls to a custom RESTful (JSON) WCF Service from Dynamics CRM, a network related error popped up. Even setting “cors: true” in the client jQuery code didn’t help. In case you’re wondering what “cors” refers to, it means Cross Origin Resource Sharing. By enabling it, you are allowing cross-domain communication from the browser. Anyways, since that didn’t help, this is where the following solution comes into play. The trick here is to make some changes in the server side, that is, in the WCF Service code to make the request happen successfully. The changes – that’s exactly what we’re going to see in this article. But instead of going straight to the solution, let’s try to reproduce the issue and then apply the fix.
Call WCF Service from Dynamics CRM – The Problem
Let’s start with a very basic JSON WCF Service. Just one simple method, that takes in a single argument and prepends a fixed string “MyWCFResponse” to it. This is just for demonstration, so to keep it simple it’s GET, so the parameter is passed in the URL itself.

Call WCF Service from Dynamics CRM 2013 using AJAX – Image 01
The contents of “IService.cs” being as follows:
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace RestWcfService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(UriTemplate = "getdata/{value}", Method = "GET", ResponseFormat =WebMessageFormat.Json)]
Response GetData(string value);
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace RestWcfService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
[ServiceContract]
public interface IService
{
[OperationContract]
[WebInvoke(UriTemplate = "getdata/{value}", Method = "GET", ResponseFormat =WebMessageFormat.Json)]
Response GetData(string value);
}
}
|
The implemented class “Service.svc.cs” has the following contents:
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace RestWcfService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
public class Service : IService
{
public Response GetData(string value)
{
return new Response()
{
Data = "MyWCFResponse" + value,
Status = "OK"
};
}
}
public class Response
{
public string Data { get; set; }
public string Status { get; set; }
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
namespace RestWcfService
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together.
// NOTE: In order to launch WCF Test Client for testing this service, please select Service1.svc or Service1.svc.cs at the Solution Explorer and start debugging.
public class Service : IService
{
public Response GetData(string value)
{
return new Response()
{
Data = "MyWCFResponse" + value,
Status = "OK"
};
}
}
public class Response
{
public string Data { get; set; }
public string Status { get; set; }
}
}
|
And a simple “web.config” to enable JSON behavior:
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="RestWcfService.Service">
<endpoint address="" binding="webHttpBinding" contract="RestWcfService.IService"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
|
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="RestWcfService.Service">
<endpoint address="" binding="webHttpBinding" contract="RestWcfService.IService"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false before deployment -->
<serviceMetadata httpGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
|
Now, after you have built the solution and deployed it in IIS, we are going to try and invoke it from Dynamics CRM using a jQuery Ajax call. One thing to be noted here is that, the Dynamics CRM is installed in a different server than the one where we have hosted the WCF Service. Although, some development environments follow everything-inside-a-single-box nomenclature, when it comes to production environments, Dynamics CRM servers are always maintained separately from additional custom components. So, we are going to simulate a production environment nomenclature here.
Call WCF Service from Dynamics CRM 2013 using AJAX – Image 02
We are going to be using the following piece of code On Load of Contact form in Dynamics CRM to fill up a particular field with the value returned from the WCF Service.
{
var fname = Xrm.Page.getAttribute("firstname").getValue();
if(fname != null || fname != 'undefined' || fname != "")
{
jQuery.support.cors = true;
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: 'http://192.168.164.139/RestWcfService/Service.svc/getdata/' + fname,
processData: false,
dataType: "json",
success: function (response) {
if(response != null || response != 'undefined')
{
var respData = response.Data;
Xrm.Page.getAttribute("lastname").setValue(respData);
}
},
error: function (a, b, c) {
alert(a.responseText);
}
});
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
function ContactOnLoad()
{
var fname = Xrm.Page.getAttribute("firstname").getValue();
if(fname != null || fname != 'undefined' || fname != "")
{
jQuery.support.cors = true;
$.ajax({
type: "GET",
contentType: "application/json; charset=utf-8",
url: 'http://192.168.164.139/RestWcfService/Service.svc/getdata/' + fname,
processData: false,
dataType: "json",
success: function (response) {
if(response != null || response != 'undefined')
{
var respData = response.Data;
Xrm.Page.getAttribute("lastname").setValue(respData);
}
},
error: function (a, b, c) {
alert(a.responseText);
}
});
}
}
|
For demo purposes, we are simply fetching the First Name of the Contact record, passing it to the WCF Service and updating the Last Name of the Contact with the response received from the Service. The code looks okay, except when you run it, it encounters an error.
Call WCF Service from Dynamics CRM 2013 using AJAX – Image 03
Debugging the code shows that it’s going directly to the error callback, contrary to what we had expected.
Call WCF Service from Dynamics CRM 2013 using AJAX – Image 04
You might be clueless about what’s going on. This where F12 (IE developer tools) comes to aid. Popping it up by pressing F12 shows the actual cause behind the problem – “Network Error, Access is denied”.
Call WCF Service from Dynamics CRM 2013 using AJAX – Image 05
Call WCF Service from Dynamics CRM – The Solution
Now that we have been reproduce the issue, let’s go ahead and fix it. Open up your WCF Service code in Visual Studio. Add the “Global.asax” file to your project by right clicking on the Project > Add > New Item > Global Application Class.
Call WCF Service from Dynamics CRM 2013 using AJAX – Image 06
Call WCF Service from Dynamics CRM 2013 using AJAX – Image 07
Open up the “Global.asax” file and add the following piece of code:
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
|
protected void Application_BeginRequest(object sender, EventArgs e)
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Origin", "*");
if (HttpContext.Current.Request.HttpMethod == "OPTIONS")
{
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Methods", "GET, POST");
HttpContext.Current.Response.AddHeader("Access-Control-Allow-Headers", "Content-Type, Accept");
HttpContext.Current.Response.AddHeader("Access-Control-Max-Age", "1728000");
HttpContext.Current.Response.End();
}
}
|
Save the file, recompile your Service code and re-deploy it to IIS. That’s it! Now head back to Dynamics CRM and try opening up a Contact record, you should be able to see the effect of the code!
Call WCF Service from Dynamics CRM 2013 using AJAX – Image 08
See how the last name is replaced with (“MyWCFResponse” + First Name) which was returned by the WCF Service. Opening up the Developer Tools (F12) shows that there are no network related errors as were shown earlier.
Call WCF Service from Dynamics CRM 2013 using AJAX – Image 09
Well, that’s it. If you’re reading it right now, I hope this saved some of your time and helped you! =) And this is not something specific for Dynamics CRM, it’s something that works for any jQuery ajax calls.
MSCRM 通过Ajax调用WCF服务的更多相关文章
- ajax内调用WCF服务
WCF可以当作WebService一样被调用,在html内通过ajax调用WCF服务的方法如下: 1.新建一个WCF服务的网站项目: 2.在项目内增加一个新项:启用了ajax的WCF服务: 3.在对应 ...
- WCF入门教程(四)通过Host代码方式来承载服务 一个WCF使用TCP协议进行通协的例子 jquery ajax调用WCF,采用System.ServiceModel.WebHttpBinding System.ServiceModel.WSHttpBinding协议 学习WCF笔记之二 无废话WCF入门教程一[什么是WCF]
WCF入门教程(四)通过Host代码方式来承载服务 Posted on 2014-05-15 13:03 停留的风 阅读(7681) 评论(0) 编辑 收藏 WCF入门教程(四)通过Host代码方式来 ...
- jquery ajax调用WCF,采用System.ServiceModel.WebHttpBinding
Jquery ajax调用WCF服务 例子效果如下:原界面 点击按钮GetList get后,通过指定的Url获取数据添加到table 新建一个控制台项目,添加IContract.cs,DBServi ...
- 【原创经验分享】JQuery(Ajax)调用WCF服务
最近在学习这个WCF,由于刚开始学 不久,发现网上的一些WCF教程都比较简单,感觉功能跟WebService没什么特别大的区别,但是看网上的介绍,就说WCF比WebService牛逼多少多少,反正我刚 ...
- 实现jquery.ajax及原生的XMLHttpRequest跨域调用WCF服务的方法
关于ajax跨域调用WCF服务的方法很多,经过我反复的代码测试,认为如下方法是最为简便的,当然也不能说别人的方法是错误的,下面就来上代码,WCF服务定义还是延用上次的,如: namespace Wcf ...
- 实现jquery.ajax及原生的XMLHttpRequest调用WCF服务的方法
废话不多说,直接讲解实现步骤 一.首先我们需定义支持WEB HTTP方法调用的WCF服务契约及实现服务契约类(重点关注各attribute),代码如下: //IAddService.cs namesp ...
- 实现在GET请求下调用WCF服务时传递对象(复合类型)参数
WCF实现RESETFUL架构很容易,说白了,就是使WCF能够响应HTTP请求并返回所需的资源,如果有人不知道如何实现WCF支持HTTP请求的,可参见我之前的文章<实现jquery.ajax及原 ...
- [转]学习 WCF (6)--学习调用WCF服务的各种方法
转自:http://www.cnblogs.com/gaoweipeng/archive/2009/07/26/1528263.html 作者这篇博文写得很全面. 根据不同的情况,我们可以用不同的方法 ...
- VS2010中使用Jquery调用Wcf服务读取数据库记录
VS2010中使用Jquery调用Wcf服务读取数据库记录 开发环境:Window Servere 2008 +SQL SERVE 2008 R2+ IIS7 +VS2010+Jquery1.3.2 ...
随机推荐
- TF-IDF算法 笔记
TF-IDF:Term Frequency-Inverse Document Frequency(词频-逆文档频度):主要用来估计一个词在一个文档中的重要程度. 符号说明: 文档集:D={d1,d2, ...
- iOS 之 微信开发流程
第1阶段 注册开放平台帐号 注册成为微信开放平台开发者 立即注册 认证开发者资质 开发者资质认证通过后才可申请微信支付,申请审核服务费:300元/次 立即认证 创建APP并提交审核 提交你的APP基本 ...
- dev中TreeList的应用(转)
如果需要在单元格添加时则用TreeList如果只是单纯读取数据或检索数据时则用GridControl 1.如果点击添加 时则添加TreeList的节点: protected internal void ...
- 解决mysql 1864 主从错误
从字面意思看了一下是因为slave_pending_jobs_size_max默认值为16777216(16MB),但是slave接收到的slave_pending_jobs_size_max为 ...
- Java jsp 示例
<!DOCTYPE html> <!-- [ published at 2015-11-13 12:30:50 ] --> <html> <head> ...
- 企业为什么要实行ERP系统,它到底有什么好处呢?
目前,我国正在大力推行企业信息化建设,作为一种包含了现代管理思想的ERP(Enterprise Resource Planning)系统日益成为现代企业业务运作的主要工具,为了提升管理水平,提升企业竞 ...
- swift版 关于微信支付的那点事
今天心情那真是想要强奸吉娃娃的冲动 说白了就是不想做和工作沾边的任何事 但是也不能闲着啊 时间那么贵 之前就想把微信支付做一下 主要就是怕自己忘记了 今天难得有时间 就来简单的记录一下 旨 ...
- backbone 1.1.2 api
Backbone.js为复杂WEB应用程序提供模型(models).集合(collections).视图(views)的结构.其中模型用于绑定键值数据和自定义事件:集合附有可枚举函数的丰富API: 视 ...
- sqlcmd命令导入大容量的SQL本地文件至SQL server 2008
由于开发工作在测试环境,需要构造测试数据,经常遇到100+M大小的*.sql文件需要导入到测试库的情况,由于SSMS里对导入文件的大小有限制: 会出现上图的报错!上网查了下,超过80M的文件是不能在S ...
- 原生JS获取HTML样式并修改
大家都知道在JavaScript原生操作中获取元素的样式,在实际操作是使用时比较频繁的一件事,这里像大家介绍下获取css样式的方法,希望可以帮助一些需要的人,如果有幸被大牛看到,有更好的办法,欢迎提出 ...