D365 Online中SiteMap加载的HTML Web Resource的Xrm对象问题咨询
Let's break down your confusion and get you the compliant, future-proof solution you need:
First, clearing up the documentation vs. behavior discrepancies
- The confusion around
ClientGlobalContext.js.aspxcomes from a key detail: Microsoft’s docs state this script doesn’t directly provide theXrmobject—that’s correct. Its primary purpose is to expose theGetGlobalContext()method. The reason you sawXrmworking when you included it is because your Angular HTML Web Resource is loaded as part of the SiteMap, meaning it’s embedded within the main model-driven app’s frame. TheXrmobject was already present from the parent app, and including the script didn’t overwrite or block it. - As for
parent.Xrmworking despite docs saying it shouldn’t: Older docs might have described scenarios where Web Resources are loaded in isolated popups (whereparentwouldn’t point to the main app frame), but when loaded directly in the SiteMap (as part of the main app’s UI), your Web Resource lives in a subframe whereparentdoes reference the main app’s window. That said, relying onparent.Xrmis risky—if Microsoft ever changes the app’s frame structure, this could break.
The compliant, non-deprecated approach
The official, future-proof way to access the client API (including Web API methods like retrieveMultipleRecords) is to use the global context retrieved via GetGlobalContext()—this is explicitly recommended by Microsoft and avoids relying on fragile frame references or direct Xrm access.
Here’s how to implement it properly:
- Keep the reference to
ClientGlobalContext.js.aspx(this is required to getGetGlobalContext()):
<head> <!-- Reference the global context script --> <script src="ClientGlobalContext.js.aspx" type="text/javascript"></script> </head>
- Use the context object instead of direct
Xrmcalls:
// Get the global context const globalContext = GetGlobalContext(); // Call Web API via the context object globalContext.webApi.retrieveMultipleRecords("account", "?$select=name,accountid") .then((result) => { // Handle your retrieved records console.log("Records retrieved:", result.entities); }) .catch((error) => { console.error("Error fetching records:", error); });
Why this is better than your current workarounds
- Avoids frame dependency:
GetGlobalContext()works regardless of how your Web Resource is loaded (SiteMap, popup, etc.)—it doesn’t rely onparentor directXrmaccess. - Future-proof: This method is explicitly documented and supported by Microsoft, so you don’t have to worry about it being deprecated or breaking in future model-driven app updates.
If you absolutely don’t want to include ClientGlobalContext.js.aspx, you can use Xrm.Utility.getGlobalContext()—but you need to ensure Xrm is fully initialized first (since it depends on the parent app’s Xrm object). Here’s a safe way to do that:
function initializeApp() { if (typeof Xrm !== "undefined") { const globalContext = Xrm.Utility.getGlobalContext(); // Proceed with your Web API calls here } else { // Retry if Xrm isn't loaded yet setTimeout(initializeApp, 100); } } document.addEventListener("DOMContentLoaded", initializeApp);
That said, the first approach with ClientGlobalContext.js.aspx is still the most reliable.
内容的提问来源于stack exchange,提问作者Sai Krishna

