Javascript从Dynamics Online发布到外部站点

Javascript从Dynamics Online发布到外部站点,javascript,jquery,dynamics-crm,Javascript,Jquery,Dynamics Crm,当OnSave事件从Microsoft Dynamics 365表单触发时,我一天中的大部分时间都在尝试将数据发布到外部WebAPI端点。不幸的是,尽管进行了大量的研究,我还是未能成功地发布数据 我花了大约一个小时的时间在以正确的形式引用javascript库的问题上磕磕绊绊,然后尝试从脚本中引用jQuery,并尝试使用声明的别名使用$.ajax触发帖子。以下是该代码的修订版本: function UpdateSupplierStatus() { var $jQ = jQuery.noCo

当OnSave事件从Microsoft Dynamics 365表单触发时,我一天中的大部分时间都在尝试将数据发布到外部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.")
});
}
无论我尝试什么,似乎只要我尝试执行post,我就会直接陷入“错误”条款。在使用Internet Explorer调试脚本时,我在后台运行了Fiddler,没有尝试命中指定的端点-它只是没有尝试,只是出错

我做了一些研究,发现有人建议使用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));
}
同样,如果我调试它是不成功的,但是这次似乎有问题的行是'req.open'(…)-据我所知,建议我不能使用XmlHttpRequest向主机域以外的资源发出请求。这里的问题是CRM托管,相关网站显然在其他地方。有人将“修复”描述为要求用户更改其安全设置,但坦率地说,我发现这是错误的s-我不能也不会要求我的客户更改他们的安全设置,以使其能够工作

我在这里遗漏了什么?使用Dynamics 365将数据发布到外部站点是否真的如此困难,或者是否有一些我遗漏的过程可以促进这一点

编辑 因此,我尝试使用不同的浏览器进行测试,使用XmlHttpRequest方法比使用$.ajax方法更进一步。但是,我没有自签名本地主机,并且我们的登台环境没有SSL证书,因此我无法通过HTTPS提供内容。我现在有两个问题:

我不能要求人们不使用IE
无论是在我的开发环境中,还是在我的登台环境中,我都无法轻松地让HTTPS工作


我开始越来越觉得这不是Dynamics的问题!

这不是Dynamics 365的问题,而是CORS的问题:

出于安全原因,浏览器限制跨源HTTP请求 从脚本中启动。例如,XMLHttpRequest和Fetch 遵循同源策略。因此,使用 XMLHttpRequest或Fetch只能对其自身进行HTTP请求 域名

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

您将发现许多关于执行跨域请求的不同场景和不同方式的示例(在前面的链接中,您将找到许多此类信息)

下面是一个“简单的请求”,我认为它在您的场景中会起作用(允许的方法是GET、HEAD和POST),如果您愿意,您可以直接从CRM进行测试(我已经完成了,您可以在我上传的屏幕截图中看到这一点):

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


如您所见,服务器(在您的场景中)也必须配置为显式允许跨域请求。您可以在下面看到启用此选项的非常详细的教程(假设您使用的是WebAPI).

您的jQuery ajax调用不起作用,因为您没有将函数定义传递给错误处理程序,而是直接执行一些代码(警报…)

尝试将代码包装到内联函数定义中,如下所示:

$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之后):

此外,请确保您的Web服务接受跨源请求。若要在Web API项目中执行此操作,请进行以下更改:

  • 安装Nuget软件包Microsoft.AspNet.WebApi.Cors
  • 将以下属性添加到类中:

    [EnableCors(来源:“*”,标题:“*”,方法:“*”,公开标题:”)]
    公共类成员资格ApiController:ApiController

  • 在web.config的标记下添加以下内容:

    
    


最后一步是在响应中包含这两个头。当这些头丢失时,浏览器将阻止响应。我很确定您丢失了web.config中的xml标记。

您是否在
myurl.com
服务器上实现了CORS?抱歉,@HenkvanBoeijen,我不确定您的意思是什么?CORS是什么?请参阅答案of Frederico Jousset.嗨@HenkvanBoeijen-谢谢;我尝试过实现Cors,但这没有帮助。当然,我并不是一夜之间就成为Cors专家,但我有理由相信我已经做了足够多的工作,如果这是问题的话。你有什么其他想法我可以尝试吗?你可以试试Fiddler,看看服务器会发送什么响应。嗨@federico jousset-感谢您的回复,但我不认为这是Cors问题,原因有两个:首先,我在通过PC访问CRM并调试同一台机器上的API端点时尝试了这一点,将CRM中的JS更改为适当地指向本地主机。因此,如果我使用ajax.Post方法,则原点和目标都是相同的在相同的来源中,但我看到了相同的症状。其次,我尝试使用您的方法,使用XmlHttpRequest,并在方法的属性中添加了EnableCors(来源:,标题:,方法:“*”)-没有乐趣。如果它们是
$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."); }
});
$jQ.support.cors = true;