geekfujiwara/codeappsdevelopmentstandard/model-driven-app

Claude Code and agent skill by geekfujiwara/codeappsdevelopmentstandard

Trust tier 3
  • community
Source check pending

Checking that the SKILL.md file is still in the repository.

モデル駆動型アプリを Dataverse Web API(appmodules / sitemaps テーブル)で作成・構成・公開する。

Install

npx vskill@latest install geekfujiwara/codeappsdevelopmentstandard/model-driven-app

SKILL.md

モデル駆動型アプリ構築スキル

Dataverse Web API(appmodules / sitemaps テーブル)でモデル駆動型アプリを ソリューション対応で 作成・構成・公開する。

前提: setup_dataverse.py で Dataverse テーブルが作成済みであること。
テーブルが存在しないとアプリに追加するコンポーネントがない。

大前提: 一つのソリューション内に開発

Dataverse テーブル・Code Apps・Power Automate フロー・Copilot Studio エージェント・モデル駆動型アプリ は すべて同一のソリューション内 に含める。 .env の SOLUTION_NAME と PUBLISHER_PREFIX を全フェーズで統一して使用する。

認証: Python スクリプトの認証は standard スキルの auth_helper.py を使用。

前提: 設計フェーズ完了後にデプロイに入る(必須)

アプリをデプロイする前に、アプリ設計をユーザーに提示し承認を得ていること。

設計提示時に含める内容:

項目内容
アプリ名表示名とユニーク名(英語のみ)
アプリ説明アプリの目的の簡潔な説明
含めるテーブル一覧ソリューション内のどのテーブルをアプリに含めるか
ナビゲーション構造SiteMap の Area/Group/SubArea 構成
ビュー・フォーム各テーブルで表示するビューとフォーム(デフォルト: 全て含む)
セキュリティロールアプリに関連付けるロール
モデル駆動型アプリ: 設計提示 → ユーザー承認 → デプロイスクリプト実行

必須要件

AppModule 作成の必須プロパティ
name: アプリの表示名(日本語 OK)
uniquename: 一意名(英語のみ。自動的にソリューション prefix が付く)
clienttype: 4(Unified Interface)★ 必須
webresourceid: アイコン用 WebResource ID
システムデフォルト: 953b9fac-1e5e-e611-80d6-00155ded156f
clienttype=4 を必ず指定する【必須】
❌ clienttype 未指定 → レガシー Web クライアント用アプリが作成される
「このアプリはレガシ Web クライアント用に設計されたものです」警告が表示
✅ clienttype=4 → Unified Interface(新しい Look & Feel)
モダンな UI で動作し、警告なし
uniquename は英語のみ
✅ uniquename: "ProjectManagement"
❌ uniquename: "プロジェクト管理"
→ 英数字とアンダースコアのみ許容
→ 作成時にソリューション publisher prefix が自動付与(例: new_ProjectManagement)
SiteMap が必須(ValidateApp で検証される)
❌ SiteMap なしで AppModule を作成 → ValidateApp で "App does not contain Site Map" エラー
✅ SiteMap を先に作成し、AddAppComponents でアプリに追加
SiteMap XML の正式フォーマット【必須】
xml
<SiteMap IntroducedVersion="7.0.0.0">
<Area Id="MainArea" ShowGroups="true" IntroducedVersion="7.0.0.0">
<Titles><Title LCID="1041" Title="アプリ名" /></Titles>
<Group Id="grp_transaction" IntroducedVersion="7.0.0.0" IsProfile="false">
<Titles><Title LCID="1041" Title="業務データ" /></Titles>
<SubArea Id="sub_entity1" Entity="prefix_entity1" AvailableOffline="true" />
<SubArea Id="sub_entity2" Entity="prefix_entity2" AvailableOffline="true" />
</Group>
<Group Id="grp_master" IntroducedVersion="7.0.0.0" IsProfile="false">
<Titles><Title LCID="1041" Title="マスタ" /></Titles>
<SubArea Id="sub_master1" Entity="prefix_master1" AvailableOffline="true" />
</Group>
</Area>
</SiteMap>
  • Area: ナビゲーションの最上位区分
  • Group: Area 内のグループ(複数テーブルをまとめる)
  • SubArea: 個別テーブルへのナビゲーション。Entity は 論理名(例: geek_project)
  • 複数の Area / Group を定義可能(例: マスタデータとトランザクションデータを分離)
ShowGroups="true" を必ず指定する【必須】
❌ ShowGroups 未指定 or "false" → グループヘッダーが非表示
→ 最初のグループのテーブルしかナビゲーションに表示されない
✅ ShowGroups="true" → 全グループがヘッダー付きで表示される
教訓: 複数 Group がある SiteMap で ShowGroups="true" を忘れると、
最初のグループのアイテムしか表示されず、他のグループが完全に消える。
これはエラーにならず ValidateApp も通るため発見が困難。
SiteMap XML 必須属性一覧
要素必須属性説明
SiteMapIntroducedVersion="7.0.0.0"バージョニング用。Unified Interface で必要
AreaShowGroups="true", IntroducedVersion="7.0.0.0"ShowGroups がないと複数グループが表示されない
GroupIntroducedVersion="7.0.0.0", IsProfile="false"IsProfile=false でプロファイルグループと区別
SubAreaEntity, AvailableOffline="true"オフラインアクセス。モバイル対応に必要
Title は属性ではなく Titles 子要素で指定する
xml
❌ <Area Id="MainArea" Title="アプリ名"> ← Title 属性は非正式
✅ <Area Id="MainArea" ShowGroups="true" IntroducedVersion="7.0.0.0">
<Titles><Title LCID="1041" Title="アプリ名" /></Titles>
LCID="1041" は日本語。英語は 1033。
Title 属性でも動作する場合があるが、正式フォーマットは Titles 子要素。
SiteMap レコードは isappaware: true で作成
python
body = {
"sitemapname": "MyApp_SiteMap",
"sitemapnameunique": "MyApp_SiteMap",
"sitemapxml": sitemap_xml,
"isappaware": True, # ← 必須。アプリ固有 SiteMap として認識される
}
コンポーネント追加は AddAppComponents アクション
python
# SiteMap の追加
api_post("AddAppComponents", {
"AppId": app_id,
"Components": [
{"sitemapid": sitemap_id, "@odata.type": "Microsoft.Dynamics.CRM.sitemap"},
]
})
# ビュー(savedquery)の追加
api_post("AddAppComponents", {
"AppId": app_id,
"Components": [
{"savedqueryid": view_id, "@odata.type": "Microsoft.Dynamics.CRM.savedquery"},
]
})
# フォーム(systemform)の追加
api_post("AddAppComponents", {
"AppId": app_id,
"Components": [
{"formid": form_id, "@odata.type": "Microsoft.Dynamics.CRM.systemform"},
]
})
注意: テーブルのビューとフォームを追加すると、テーブルも自動的にアプリに含まれる。
ただし AppComponents.Entities は空のままになる場合がある(appmodulecomponent テーブルに Entity Type=1 のレコードが自動作成されない)。
これはアプリの動作には影響しない。SiteMap の SubArea で Entity を指定していれば正常にナビゲーションに表示される。
AddAppComponents のバッチ分割パターン
大量のコンポーネント(ビュー・フォーム × 複数テーブル)を一度に送信すると失敗する場合がある。
✅ 50 件ずつバッチ分割して送信
✅ バッチ失敗時は 1 件ずつフォールバック(既に追加済みのコンポーネントをスキップ)
Entity コンポーネント (Type=1) は API で直接追加できない
❌ appmodulecomponent テーブルへの POST → "The 'Create' method does not support entities of type 'appmodulecomponent'"
❌ appmodules の collection-valued ナビゲーションプロパティへの deep insert → 非対応
✅ AddAppComponents で savedquery/systemform を追加すれば、SiteMap 経由でテーブルが表示される
教訓: Market Insight App のように UI で作成したアプリは Entity (Type=1) コンポーネントが登録されるが、
API で作成したアプリでは savedquery/systemform のみが登録される。これは正常動作であり修正不要。
ビューとフォームの取得パターン
python
# テーブルのシステムビュー(querytype=0 = Public View)
views = api_get("savedqueries", {
"$filter": f"returnedtypecode eq '{entity_logical_name}' and querytype eq 0",
"$select": "savedqueryid,name",
})
# テーブルのメインフォーム(type=2 = Main Form)
forms = api_get("systemforms", {
"$filter": f"objecttypecode eq '{entity_logical_name}' and type eq 2",
"$select": "formid,name",
})
セキュリティロール関連付け
python
# appmoduleroles_association ナビゲーションプロパティで関連付け
requests.post(
f"{API}/appmodules({app_id})/appmoduleroles_association/$ref",
headers=headers,
json={"@odata.id": f"{API}/roles({role_id})"}
)
  • Basic User(旧 Common Data Service User)ロールを最低限関連付ける
  • 追加のカスタムロールがあれば同様に関連付け
ValidateApp で事前検証
python
result = api_get(f"ValidateApp(AppModuleId={app_id})")
# ValidationSuccess: true/false
# ValidationIssueList: エラー/警告の配列
  • SiteMap がない → Error
  • テーブルにフォーム/ビュー参照がない → Warning
PublishXml でアプリ公開
python
publish_xml = (
f"<importexportxml>"
f"<appmodules><appmodule>{app_id}</appmodule></appmodules>"
f"</importexportxml>"
)
api_post("PublishXml", {"ParameterXml": publish_xml})
個別テーブルの PublishXml(ビュー・フォーム変更時)
python
# ビュー・フォーム・アイコンなどテーブル単位の変更を公開する場合
publish_xml = (
'<importexportxml>'
f'<entities><entity>{entity_logical_name}</entity></entities>'
'</importexportxml>'
)
api_post("PublishXml", {"ParameterXml": publish_xml})
PublishXml vs PublishAllXml: テーブル単位の変更は <entities> で個別公開するのが高速。
PublishAllXml は全コンポーネントを公開するため時間がかかる。
アプリ URL フォーマット
✅ {DATAVERSE_URL}/main.aspx?appid={app_id}
❌ {DATAVERSE_URL}/apps/{app_id} ← 動作しない
デプロイスクリプトは完了時に .env へ APP_MODULE_ID を自動保存する。
この値は deploy_security_role.py のアプリ関連付けステップで使用される。
ソリューション含有の検証
python
# AppModule (ComponentType=80)
api_post("AddSolutionComponent", {
"ComponentId": app_id,
"ComponentType": 80,
"SolutionUniqueName": SOLUTION_NAME,
"AddRequiredComponents": False,
"DoNotIncludeSubcomponents": False,
})
# SiteMap (ComponentType=62)
api_post("AddSolutionComponent", {
"ComponentId": sitemap_id,
"ComponentType": 62,
"SolutionUniqueName": SOLUTION_NAME,
"AddRequiredComponents": False,
"DoNotIncludeSubcomponents": False,
})
べき等デプロイパターン
python
# 既存アプリ検索
existing = api_get("appmodules", {
"$filter": f"uniquename eq '{APP_UNIQUE_NAME}'",
"$select": "appmoduleid,name"
})
if existing["value"]:
app_id = existing["value"][0]["appmoduleid"]
# 更新(PATCH)
api_patch(f"appmodules({app_id})", {"name": new_name, "description": new_desc})
else:
# 新規作成(POST)
api_post("appmodules", body)

.env パラメータ

全パラメータの定義(取得元コメント付き)は references/.env.example を参照。 実値はリポジトリルートの .env に置く(.gitignore 済み)。

env
# === 必須(共通)===
DATAVERSE_URL=https://{org}.crm7.dynamics.com/
TENANT_ID={your-tenant-id}
SOLUTION_NAME=ProjectManagement
PUBLISHER_PREFIX=geek
# === モデル駆動型アプリ オプション ===
APP_DISPLAY_NAME=プロジェクト管理 # 未設定時は SOLUTION_NAME から生成
APP_UNIQUE_NAME=ProjectManagement # 未設定時は SOLUTION_NAME を使用
APP_DESCRIPTION=プロジェクト管理アプリ # 未設定時は自動生成

デプロイ・設計パターン

デプロイスクリプト・ナビゲーション設計パターンの詳細は デプロイリファレンス を参照。

トラブルシューティングは トラブルシューティング を参照。

コンポーネントタイプ定数

コンポーネントComponentTypeOData Type
SiteMap62Microsoft.Dynamics.CRM.sitemap
AppModule80Microsoft.Dynamics.CRM.appmodule
Entity (テーブル)1—
View (savedquery)26Microsoft.Dynamics.CRM.savedquery
Form (systemform)60Microsoft.Dynamics.CRM.systemform
Dashboard60—
Security Role20Microsoft.Dynamics.CRM.role

クイックリファレンス: 必須要件

This is the start of the file. Read the full SKILL.md on GitHub.

Security

  • Security scanPassed, 95 of 100Pattern checks on the skill's files.
  • Model reviewPassed

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
57
Repository forks
20
7-day trend score
20

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/geekfujiwara/codeappsdevelopmentstandard/model-driven-app/badge)](https://verified-skill.com/skills/geekfujiwara/codeappsdevelopmentstandard/model-driven-app)

Something wrong with this skill or its page? Tell us.