Javascript从Dynamics Online发布到外部网站

时间:2017-04-11 13:18:38

标签: javascript jquery dynamics-crm

当从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 我开始感觉越来越像这不是动力学的问题!

2 个答案:

答案 0 :(得分:4)

这不是与Dynamics 365相关但与CORS相关的问题:

  

出于安全原因,浏览器会限制跨源HTTP请求   从脚本中启动。例如,XMLHttpRequest和Fetch   遵循同源政策。所以,一个web应用程序使用   XMLHttpRequest或Fetch只能向自己发出HTTP请求   域。

     

跨域资源共享(CORS)机制提供Web服务器   跨域访问控制,可实现安全的跨域数据   传输。现代浏览器在API容器中使用CORS - 例如   XMLHttpRequest或Fetch - 以降低跨源HTTP的风险   请求。

More information...

您会发现很多关于不同场景和执行跨域请求的不同方法的示例(在上一个链接中,您会发现很多这些信息)。

以下是一个“简单请求”,我认为它可以在你的场景中工作(允许的方法是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(); 
}

enter image description here

这个“简单请求”将使用CORS标头来处理权限:

enter image description here

如您所见,服务器(您的方案中的 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项目中执行此操作,请进行以下更改:

  • 安装Nuget包Microsoft.AspNet.WebApi.Cors
  • 将以下属性添加到您的班级:

    [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标签。