Install
$ agentstack add skill-ryanmakesandbreaksstuff-custom-codex-claude-plugins-and-skills-dataverse-web-resources ✓ scanned · ✓ verified — works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
About
Dataverse Web Resources
CRITICAL RULES
formContextis invalid afterawait. Context objects passed to event handlers are valid only during synchronous execution. After anyawaitor inside.then(),formContext.getAttribute("x").getValue()silently returnsnull— not an error. Extract the VALUES you need (strings, GUIDs, numbers) before the firstawait. Never store the context reference itself across an async boundary.
preventDefault()is synchronous-only in OnSave. Calling it afterawaitdoes nothing — the save proceeds regardless. If you need to block a save based on async validation, callpreventDefault()synchronously first, then perform the async check and re-enable if valid viasaveEventArguments.enableSaveValidation.
- Never call
formContext.data.entity.save()inside an OnSave handler. This creates a recursive save loop, producing a "Saving in Progress" runtime error visible to the user.
Xrmis completely unavailable in SiteMap SubArea web resources. NeitherXrmnorparent.Xrmis injected. The only supported approach: include `and callGetGlobalContext()for org context.Xrm.WebApi,Xrm.Navigation, and all otherXrm.*` APIs are inaccessible from these pages — there is no workaround.
- Never hardcode
/WebResources/as a URL path. In multi-org environments this silently resolves to the user's default org, not the current one — causing "File Not Found" for users in a non-default org. It also bypasses the platform's browser cache versioning token. Use$webresource:in SiteMap/Ribbon XML, orXrm.Navigation.openWebResource()in code — both embed the version token automatically.
- "Pass execution context as first parameter" MUST be checked. Without it the function receives no argument,
executionContextisundefined, and the firstgetFormContext()call crashes silently. No error is thrown at registration time.
- Async OnSave handlers have a 10-second platform timeout per handler. After timeout the save continues whether or not you called
preventDefault()— the timed-out handler is simply abandoned. Never calldisableAsyncTimeout()unless you can guarantee the async operation cannot hang.
- Always use
$selectinXrm.WebApicalls. Without it every column on every matching record is returned — including multi-line text fields and computed columns. Severe performance impact on grids and high-traffic views.
- DOM manipulation is unsupported and breaks on platform updates. PowerApps Checker (
avoid-dom-form) flags any direct DOM access in form scripts. The Unified Interface DOM is internal and undocumented. Use exclusivelyformContext.*andXrm.*client API methods.
NEVER
- NEVER use
parent.Xrm.*in a SiteMap SubArea,openWebResourcepopup, or side pane web resource —Xrmis not injected. UseClientGlobalContext.js.aspx→GetGlobalContext(). - NEVER manipulate the model-driven app DOM (
querySelector,element.style,addEventListeneron platform elements) — unsupported, breaks on platform updates, flagged by PowerApps Checker. - NEVER use synchronous
XMLHttpRequest— deprecated, blocked by PowerApps Checker, breaks async form loading. UsefetchorXrm.WebApi(promise-based only). - NEVER call
formContext.data.entity.save()inside an OnSave handler — recursive save loop → "Saving in Progress" error. - NEVER use
preventDefault()to block BPF stage navigation inside an OnSave handler — throws a runtime error. RegisterformContext.data.process.addOnPreStageChange(handler)instead and calleventArgs.preventDefault()there. - NEVER store
executionContextorformContextacross async boundaries — they become stale immediately after the synchronous event phase ends. - NEVER put logic or data you want to hide inside classic RibbonDiffXml display/enable rules — all ribbon XML downloads to and is visible in the user's browser DevTools.
Xrm Context Availability
| Web resource location | Xrm directly | parent.Xrm | Correct approach | |---|---|---|---| | Form event handler | Via executionContext.getFormContext() | N/A | Standard executionContext pattern | | HTML web resource embedded in form tab | NO | parent.Xrm.* works | parent.Xrm.Utility, parent.Xrm.Navigation | | SiteMap SubArea HTML web resource | NO | NO | ClientGlobalContext.js.aspx → GetGlobalContext() | | Opened via openWebResource() | NO | NO | ClientGlobalContext.js.aspx → GetGlobalContext() | | App side pane (Xrm.App.sidePanes) | NO | NO | ClientGlobalContext.js.aspx → GetGlobalContext() | | Ribbon JavaScript action | Not via executionContext | N/A | CrmParameter bindings in ribbon XML |
Quick Reference — Key Operations
| Operation | Method | Endpoint | |---|---|---| | Create web resource | POST | /webresourceset | | Update web resource | PATCH | /webresourceset({id}) | | Add to solution | Action | AddSolutionComponent (ComponentType=61) | | Publish | Action | PublishXml |
Loading Resources
Writing JavaScript for form events (OnLoad, OnSave, OnChange, field validation, UI manipulation): → MANDATORY: Load [resources/js-form-scripts.md](resources/js-form-scripts.md) before writing form scripts. Do NOT load ribbon or navigation files for form-script-only tasks.
HTML pages for dashboards, KPIs, embedded charts, or custom embedded UI: → MANDATORY: Load [resources/html-dashboards.md](resources/html-dashboards.md). Do NOT load js-form-scripts.md for HTML-only tasks.
Side panes, modal/modeless dialogs, or programmatic navigation (Xrm.App, Xrm.Navigation): → MANDATORY: Load [resources/navigation-side-panes.md](resources/navigation-side-panes.md). Do NOT load js-form-scripts.md for navigation-only tasks.
Command bar or ribbon customization (modern commanding JSON vs classic RibbonDiffXml): → MANDATORY: Load [resources/ribbon-command-bar.md](resources/ribbon-command-bar.md). Do NOT load js-form-scripts.md for ribbon-only tasks.
Choosing control types, field formats, navigation patterns, or page layouts before implementing: → MANDATORY: Consult [resources/ux-decision-guide.md](resources/ux-decision-guide.md) FIRST.
Creating or deploying web resources via the Web API: → Load [resources/deployment.md](resources/deployment.md).
Business Process Flow JavaScript API (stage navigation, OnPreStageChange, stage locking): → MANDATORY: Load [resources/bpf-client-api.md](resources/bpf-client-api.md) for any BPF scripting.
All 12 web resource types and their numeric Type IDs: → Load [resources/types-reference.md](resources/types-reference.md) for type/ID lookup only.
Do NOT load all files simultaneously — load only the file matching the specific task.
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: RyanMakesAndBreaksStuff
- Source: RyanMakesAndBreaksStuff/Custom-Codex-Claude-Plugins-and-Skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet — be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.