Definition
Find a good description for CORS (Cross-Origin Resource Sharing) at this link: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
Learn more about CORS here: https://youtube.com/watch?v=Ka8vG5miErk
Enabling CORS
To enable CORS on IIS for all sites on the machine:
Add or change web.config on the root website (Default Web site):
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<cors enabled="true" failUnlistedOrigins="true">
<add origin="*"/>
<add origin="https://www.test-cors.org" allowCredentials="true" >
<allowHeaders allowAllRequestedHeaders="true"/>
</add>
</cors>
</system.webServer>
</configuration>To do this at the App level, change Web.config in the same way - but beware that web-config is part of the installation and will be replaced upon update.
Details from the IIS team on how to configure CORS using XML (like above):
To test that CORS is active, you can use this online tool, for example, https://www.test-cors.org/.
Just enter the root URL of your site in "Remote URL".
Contender Implementation - Cors With Dynamic Decisions
To allow dynamic decisions about which Cors entries to allow, you can now implement this model pattern:

The class named TK_WebCors has a static method GetAllowOrigin(org:String):Boolean
This method will be called when you use RestAllowed Viewmodels, and the caller's Origin in small caps will be given in the parameter.
This example returns true for all, which means that all origins are ok.
A more realistic implementation might be:
MyValidCorsCallers.allinstances->select(x|x.Origin=org)->first.Allowed
The check is cached in an internal Dictionary for 10 minutes; changes will be discovered in 10-minute intervals.
If the model pattern is wrong, you get an exception in the Turnkey log:
CentralLogging("CheckCorsHeaders - check model pattern static TK_WebCors.GetAllowOrigin(vOrigin):string", ex)
NOTE - if you have Cors-middleware in IIS or Cassini, you will not see the effect of the above since middleware will overwrite them.
If Cors headers are applied, this is what we apply:
Response.Headers.Add("Access-Control-Allow-Origin", cleanorg);
Response.Headers.Add("Access-Control-Allow-Credentials", "true");
Response.Headers.Add("Access-Control-Allow-Headers", "authorization");
Response.Headers.Add("Access-Control-Allow-Methods", "POST, GET");
Response.Headers.Add("Vary", "Origin");
You may also send (not recommended due to the open nature of the web) the credentials in the basic authentication scheme:
function myFunction(){
$.ajax({
type: "get",
url: "http://localhost:5052/TurnkeyRest/Get?command=AutoFormClass1x&id=1!45",
xhrFields: { withCredentials: true },
headers: {
"Authorization": "Basic " + btoa("theuser:thepwd")
}
}).done(function (data) {
debugger;
$('#value1').text(data);
}).fail(function (jqXHR, textStatus, errorThrown) {
debugger;
$('#value1').text(jqXHR.responseText || textStatus);
});
}
Writing to ViewModels from Javascript
Post data to a ViewModel-driven MDriven Form (i.e., not the best way, but rather a way of injecting data into the standard UI); you can proceed like this:
let formData = new FormData();
formData.append("Filter", "v");
fetch('https://YOURTURNKEYSITE/TurnkeyRest/Post?command=AutoFormSysUserSeeker', {
headers: new Headers(),
method: "POST",
mode: 'cors',
body: formData
}).then((response) => {
if (response.ok) {
return response.json()
} else {
//
}
}).then((responseJsonData) => {
callback && callback(responseJsonData);
}).catch((error) => {
console.log("getWatchHistory error " + error);
});
