Javascript從Dynamics Online發布到外部網站

[英]Javascript post to external site from Dynamics Online


I've been trying for most of the day to post data to an external WebAPI endpoint when the OnSave event is triggered from a Microsoft Dynamics 365 form. Unfortunately, despite an extraordinary amount of research, I haven't been able to successfully post the data.

當從Microsoft Dynamics 365表單觸發OnSave事件時,我一直在嘗試將數據發布到外部WebAPI端點。不幸的是,盡管進行了大量研究,但我還是無法成功發布數據。

Having spent about an hour stumbling around getting the javascript library referenced in the right form, I tried reference jQuery from within my script, and trying to use $.ajax to trigger the post, using a declared alias. Here's a redacted version of the code:

花了大約一個小時磕磕絆絆地想要以正確的形式引用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.")
});
}

No matter what I try, it seems that as soon as I try to execute the post, I fall straight into the 'error' clause. I've run Fiddler in the background whilst debugging the script using Internet Explorer, and there's no attempt made to hit the endpoint specified - it simply doesn't try, just errors.

無論我嘗試什么,似乎只要我嘗試執行帖子,我就會直接進入“錯誤”條款。我在后台運行Fiddler,同時使用Internet Explorer調試腳本,並且沒有嘗試命中指定的端點 - 它只是不嘗試,只是錯誤。

I did some research, and came across a number of articles like this that suggest using XmlHttpRequest instead of trying to poke posts around the internet using jQuery, and so I tried using this instead:

我做了一些研究,並且發現了許多像這樣的文章建議使用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));
}

Again, if I debug this it's unsuccessful, however this time it seems that the offending line is 'req.open(...' - from what I've read, the suggestion is that I can't use XmlHttpRequest to make requests to resources outside of the hosts domain. The problem here is that CRM is hosted and the related website is obviously elsewhere. There is a question around this problem that describes the 'fix' as requiring users to alter their security settings, but frankly I find this to be madness - I cannot, and will not, require my customers to alter their security settings to allow this to work.

再次,如果我調試它不成功,但這次似乎違規行是'req.open(...' - 從我讀過的,我的建議是我不能使用XmlHttpRequest來發出請求主機域之外的資源。這里的問題是CRM托管,相關網站顯然是其他地方。有一個問題圍繞這個問題描述'修復'要求用戶改變他們的安全設置,但坦率地說,我發現這個瘋狂 - 我不能,也不會,要求我的客戶改變他們的安全設置以使其工作。

What am I missing here? Is it really this difficult to post data to an external site using Dynamics 365, or is there some process that I'm missing that facilitates exactly this?

我在這里想念的是什么?使用Dynamics 365將數據發布到外部站點真的很難嗎,或者是否有一些我缺少的過程正是如此?

Edit So I've tried testing this with a different browser and I get further using the XmlHttpRequest method than I was getting with the $.ajax method. However, I've not self-signed localhost, and our staging environment has no SSL certificate, and so I can't supply the content via HTTPS. I now have two issues:

編輯所以我嘗試使用不同的瀏覽器進行測試,然后我使用XmlHttpRequest方法進一步使用$ .ajax方法。但是,我沒有自簽名localhost,我們的暫存環境沒有SSL證書,因此我無法通過HTTPS提供內容。我現在有兩個問題:

I can't require people to not use IE
I can't easily get HTTPS working in either my development environment, or in my staging environment

I'm starting to feel more and more like this isn't a problem with Dynamics!

我不能要求人們不使用IE我不能輕易地讓HTTPS在我的開發環境中工作,或者在我的暫存環境中我開始感覺越來越多,這對於Dynamics來說不是問題!

2 个解决方案

#1


4  

This is not an issue related to Dynamics 365 but related to CORS:

這不是與Dynamics 365相關但與CORS相關的問題:

For security reasons, browsers restrict cross-origin HTTP requests initiated from within scripts. For example, XMLHttpRequest and Fetch follow the same-origin policy. So, a web application using XMLHttpRequest or Fetch could only make HTTP requests to its own domain.

出於安全原因,瀏覽器會限制從腳本中發起的跨源HTTP請求。例如,XMLHttpRequest和Fetch遵循同源策略。因此,使用XMLHttpRequest或Fetch的Web應用程序只能向其自己的域發出HTTP請求。

The Cross-Origin Resource Sharing (CORS) mechanism gives web servers cross-domain access controls, which enable secure cross-domain data transfers. Modern browsers use CORS in an API container - such as XMLHttpRequest or Fetch - to mitigate risks of cross-origin HTTP requests.

跨源資源共享(CORS)機制為Web服務器提供跨域訪問控制,從而實現安全的跨域數據傳輸。現代瀏覽器在API容器中使用CORS(例如XMLHttpRequest或Fetch)來降低跨源HTTP請求的風險。

More information...

更多信息...

You will find a lot of examples about different scenarios and different ways to perform a cross-domain request (in the previous link you will find a lot of these information).

您將找到許多關於不同場景和執行跨域請求的不同方法的示例(在上一個鏈接中,您將找到大量這些信息)。

The following it's a "simple request", which I think it will work in your scenario (the allowed methods are GET, HEAD and POST), and you can test it directly from CRM if you want (I've done it without problems as you can see in the screenshot that I've also uploaded):

以下是一個“簡單請求”,我認為它可以在你的場景中工作(允許的方法是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

This "simple request" will use CORS headers to handle the privileges:

這個“簡單請求”將使用CORS頭來處理權限:

enter image description here

As you can see, the server (http://myurl.com in your scenario) also has to be configured to explicitly allow cross-domain requests. You can see a very detailed tutorial to enable this option in the following MSDN article (assuming that you're using WebAPI).

如您所見,服務器(您的方案中的http://myurl.com)也必須配置為明確允許跨域請求。您可以在以下MSDN文章中看到一個非常詳細的教程來啟用此選項(假設您使用的是WebAPI)。

#2


0  

Your jQuery ajax call is not working because you are not passing a function definition to your error handler, but rather executing some code (alert...) directly.

您的jQuery ajax調用無法正常工作,因為您沒有將函數定義傳遞給錯誤處理程序,而是直接執行某些代碼(alert ...)。

Try wrapping the code in an inline function definition like this:

嘗試將代碼包裝在內聯函數定義中,如下所示:

$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."); }
});

Also, add this line in the beginning of your code (after the .noConflict):

另外,在代碼的開頭添加此行(在.noConflict之后):

$jQ.support.cors = true;

Furthermore, please make sure your webservice accepts Cross Origin Requests.To do so in your Web API project, make the following changes:

此外,請確保您的Web服務接受Cross Origin Requests。要在Web API項目中執行此操作,請進行以下更改:

  • Install the Nuget Package Microsoft.AspNet.WebApi.Cors
  • 安裝Nuget包Microsoft.AspNet.WebApi.Cors
  • Add the following attribute to your class:

    將以下屬性添加到您的類:

    [EnableCors(origins: "*", headers: "*", methods: "*", exposedHeaders: "")] public class MembershipAPIController : ApiController

    [EnableCors(起源:“*”,標題:“*”,方法:“*”,exposedHeaders:“”)]公共類MembershipAPIController:ApiController

  • Add the following in your web.config under the tag:

    在標記下的web.config中添加以下內容:

    <httpProtocol> <customHeaders> <add name="Access-Control-Allow-Origin" value="*" /> <add name="Access-Control-Allow-Methods" value="*" /> </customHeaders> <httpProtocol>

The last step is needed to include both headers in the response. When these headers are missing, the response will be blocked by the browser. I'm pretty sure you're missing the xml-tags in your web.config.

最后一步是在響應中包含兩個標頭。如果缺少這些標頭,瀏覽器將阻止響應。我很確定你錯過了web.config中的xml-tags。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2017/04/11/a827a695c8143417a690088ac0125069.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com