当从Microsoft Dynamics 365表单触发OnSave事件时,我一直在尝试将数据发布到外部WebAPI端点。不幸的是,尽管进行了大量研究,但我还是无法成功发布数据。
花了大约一个小时磕磕绊绊地想要以正确的形式引用javascript库,我尝试从我的脚本中引用jQuery,并尝试使用$ .ajax使用声明的别名来触发帖子。这是代码的编辑版本:
function UpdateSupplierStatus()
{
var $jQ = jQuery.noConflict();
var MembershipNumber =
Xrm.Page.data.entity.attributes.get("membershipnumber").getValue();
var StatusCode = Xrm.Page.data.entity.attributes.get("statuscode").getText();
$jQ.ajax({
url: 'http://myurl.com/api/MembershipAPI/UpdateMembershipStatus',
type: 'POST',
data: {
'membershipNumber' : MembershipNumber,
'statusCode' : StatusCode
},
datatype: 'json',
success: function() {},
error: alert("There was an error performing the update.")
});
}
无论我尝试什么,似乎只要我尝试执行帖子,我就会直接陷入“错误”状态。条款。我在后台运行Fiddler,同时使用Internet Explorer调试脚本,并且没有尝试点击指定的端点 - 它只是不尝试,只是错误。
我做了一些研究,并且发现a number of articles like this建议使用XmlHttpRequest而不是尝试使用jQuery在互联网上发帖,所以我尝试使用它:
function UpdateSupplierStatus()
{
var MembershipNumber = Xrm.Page.data.entity.attributes.get("membershipnumber").getValue();
var StatusCode = Xrm.Page.data.entity.attributes.get("statuscode").getText();
var Query = "?membershipNumber=" + MembershipNumber + "&statusCode=" + StatusCode;
var URL = "http://myurl.com/api/MembershipAPI/UpdateMembershipStatus";
var req = new XMLHttpRequest();
req.open("POST", URL + Query, true);
req.setRequestHeader("Accept", "application/json");
req.setRequestHeader("Content-Type", "application/json; charset=utf-8");
req.setRequestHeader("OData-MaxVersion", "4.0");
req.setRequestHeader("OData-Version", "4.0");
req.send(JSON.stringify(data));
}
同样,如果我调试它不成功,但这次看起来违规行似乎是开放的......(' - 来自我读过的内容) ,建议我不能使用XmlHttpRequest向主机域之外的资源发出请求。这里的问题是托管CRM,相关网站显然在其他地方。有a question around this problem描述了'修复'要求用户改变他们的安全设置,但坦率地说我觉得这很疯狂 - 我不能,也不会,要求我的客户改变他们的安全设置以允许它工作。
我在这里缺少什么?使用Dynamics 365将数据发布到外部站点真的很难吗,或者是否有一些我不知道的过程正是如此?
修改 所以我已经尝试使用不同的浏览器对此进行测试,并且我使用XmlHttpRequest方法比使用$ .ajax方法更进一步。但是,我没有自签名localhost,我们的暂存环境没有SSL证书,因此我无法通过HTTPS提供内容。我现在有两个问题:
我不能要求别人不使用IE
我无法轻松地在我的开发环境或我的登台环境中使用HTTPS
我开始感觉越来越像这不是动力学的问题!
答案 0 :(得分:4)
这不是与Dynamics 365相关但与CORS相关的问题:
出于安全原因,浏览器会限制跨源HTTP请求 从脚本中启动。例如,XMLHttpRequest和Fetch 遵循同源政策。所以,一个web应用程序使用 XMLHttpRequest或Fetch只能向自己发出HTTP请求 域。
跨域资源共享(CORS)机制提供Web服务器 跨域访问控制,可实现安全的跨域数据 传输。现代浏览器在API容器中使用CORS - 例如 XMLHttpRequest或Fetch - 以降低跨源HTTP的风险 请求。
您会发现很多关于不同场景和执行跨域请求的不同方法的示例(在上一个链接中,您会发现很多这些信息)。
以下是一个“简单请求”,我认为它可以在你的场景中工作(允许的方法是GET,HEAD和POST),你可以直接从CRM测试它(如果你想的话)(我已经完成了)没有问题,你可以在我上传的截图中看到):
function callOtherDomain() {
var req = new XMLHttpRequest();
var url = 'https://httpbin.org/get';
req.open('GET', url, true);
req.onreadystatechange = function() {
if (this.readyState == 4 && this.status == 200) {
alert(req.responseText);
}
};
req.send();
}
这个“简单请求”将使用CORS标头来处理权限:
如您所见,服务器(您的方案中的 http://myurl.com )也必须配置为明确允许跨域请求。您可以在以下MSDN article中看到一个非常详细的教程来启用此选项(假设您使用的是WebAPI)。
答案 1 :(得分:0)
您的jQuery ajax调用无效,因为您没有将函数定义传递给错误处理程序,而是直接执行某些代码(alert ...)。
尝试将代码包装在内联函数定义中,如下所示:
$jQ.ajax({
url: 'http://myurl.com/api/MembershipAPI/UpdateMembershipStatus',
type: 'POST',
data: {
'membershipNumber' : MembershipNumber,
'statusCode' : StatusCode
},
datatype: 'json',
success: function() {},
error: function() { alert("There was an error performing the update."); }
});
此外,在代码的开头添加此行(在.noConflict之后):
$jQ.support.cors = true;
此外,请确保您的Web服务接受Cross Origin Requests。要在Web API项目中执行此操作,请进行以下更改:
将以下属性添加到您的班级:
[EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "")]
public class MembershipAPIController : ApiController
在web.config中的标记下添加以下内容:
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="*" />
</customHeaders>
<httpProtocol>
需要在响应中包含两个标头的最后一步。如果缺少这些标头,浏览器将阻止响应。我很确定你错过了web.config中的xml标签。